[SYNCOPE-956] Console implementation
authorFrancesco Chicchiriccò <ilgrosso@apache.org>
Fri, 6 Oct 2017 15:07:52 +0000 (17:07 +0200)
committerFrancesco Chicchiriccò <ilgrosso@apache.org>
Tue, 10 Oct 2017 06:34:14 +0000 (08:34 +0200)
126 files changed:
client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java
client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
client/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java
client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java [new file with mode: 0644]
client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java [new file with mode: 0644]
client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java [new file with mode: 0644]
client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java [new file with mode: 0644]
client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersEditModalPanel.java
client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/policies/PasswordPolicyDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWrapper.java
client/console/src/main/java/org/apache/syncope/client/console/policies/PolicySpecModalPanel.java
client/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
client/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWrapper.java
client/console/src/main/java/org/apache/syncope/client/console/rest/ImplementationRestClient.java
client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksTogglePanel.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Ownership.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Resources.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/AbstractConnConfPanel.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ObjectTypeTogglePanel.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
client/console/src/main/resources/console.properties
client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyAccountRule.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyItemTransformer.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyLogicActions.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPasswordRule.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullCorrelationRule.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPushActions.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyRecipientsProvider.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyReconFilterBuilder.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyReportlet.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MySchedTaskJobDelegate.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyValidator.groovy [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Recipients.html
client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Recipients.properties
client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Recipients_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Recipients_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Recipients_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
client/console/src/main/resources/org/apache/syncope/client/console/pages/Implementations.html [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.html [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.properties [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_it.properties [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_pt_BR.properties [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_ru.properties [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.html [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationModalPanel.html [new file with mode: 0644]
client/console/src/main/resources/org/apache/syncope/client/console/panels/PlainSchemaDetails.html
client/console/src/main/resources/org/apache/syncope/client/console/panels/PlainSchemaDetails.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/PlainSchemaDetails_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/PlainSchemaDetails_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/PlainSchemaDetails_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.html
client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/panels/RealmDetails_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder$Profile.html
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicySpecModalPanel$CorrelationRulePanel.html
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicySpecModalPanel.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicySpecModalPanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicySpecModalPanel_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/policies/PolicySpecModalPanel_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletDirectoryPanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletDirectoryPanel_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletDirectoryPanel_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletWizardBuilder$Profile.html
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletWizardBuilder$Profile.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletWizardBuilder$Profile_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletWizardBuilder$Profile_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/reports/ReportletWizardBuilder$Profile_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.html
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ru.properties
client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ObjectTypeTogglePanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.html
client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.properties
client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_it.properties
client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_pt_BR.properties
client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ru.properties
common/lib/src/main/java/org/apache/syncope/common/lib/report/ReconciliationReportletConf.java
common/lib/src/main/java/org/apache/syncope/common/lib/to/PlainSchemaTO.java
core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AccountRule.java
core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordRule.java
core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/Reportlet.java
core/persistence-jpa/src/test/resources/domains/MasterContent.xml
core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel.java

index 95d5628..4da9446 100644 (file)
@@ -61,7 +61,7 @@ public class SchemaResultManager extends CommonsResultManager {
         System.out.println("    conversion pattern: " + schemaTO.getConversionPattern());
         System.out.println("    mandatory condition: " + schemaTO.getMandatoryCondition());
         System.out.println("    mime type: " + schemaTO.getMimeType());
-        System.out.println("    validator class: " + schemaTO.getValidatorClass());
+        System.out.println("    validator class: " + schemaTO.getValidator());
         System.out.println("    cipher algorithm: " + (schemaTO.getCipherAlgorithm() == null
                 ? "" : schemaTO.getCipherAlgorithm().getAlgorithm()));
         System.out.println("");
index 5449097..c71fdbc 100644 (file)
@@ -121,6 +121,8 @@ public final class Constants {
 
     public static final String PREF_NOTIFICATION_PAGINATOR_ROWS = "notification.paginator.rows";
 
+    public static final String PREF_IMPLEMENTATION_PAGINATOR_ROWS = "implementation.paginator.rows";
+
     public static final String PREF_MAIL_TEMPLATE_PAGINATOR_ROWS = "mail.template.paginator.rows";
 
     public static final String PREF_PROPAGATION_TASKS_PAGINATOR_ROWS = "proagationtasks.paginator.rows";
index 7a39743..ed60e6c 100644 (file)
@@ -21,7 +21,9 @@ package org.apache.syncope.client.console.init;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.syncope.client.console.pages.BaseExtPage;
@@ -32,6 +34,9 @@ import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.SSOLoginFormPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
 import org.apache.syncope.client.console.widgets.BaseExtWidget;
+import org.apache.syncope.common.lib.policy.AccountRuleConf;
+import org.apache.syncope.common.lib.policy.PasswordRuleConf;
+import org.apache.syncope.common.lib.report.ReportletConf;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@@ -42,7 +47,7 @@ public class ClassPathScanImplementationLookup {
 
     private static final Logger LOG = LoggerFactory.getLogger(ClassPathScanImplementationLookup.class);
 
-    private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.client.console";
+    private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope";
 
     private List<Class<? extends BasePage>> pages;
 
@@ -54,6 +59,12 @@ public class ClassPathScanImplementationLookup {
 
     private List<Class<? extends SSOLoginFormPanel>> ssoLoginFormPanels;
 
+    private Map<String, Class<? extends ReportletConf>> reportletConfs;
+
+    private Map<String, Class<? extends AccountRuleConf>> accountRuleConfs;
+
+    private Map<String, Class<? extends PasswordRuleConf>> passwordRuleConfs;
+
     /**
      * This method can be overridden by subclasses to customize classpath scan.
      *
@@ -70,6 +81,9 @@ public class ClassPathScanImplementationLookup {
         extPages = new ArrayList<>();
         extWidgets = new ArrayList<>();
         ssoLoginFormPanels = new ArrayList<>();
+        reportletConfs = new HashMap<>();
+        accountRuleConfs = new HashMap<>();
+        passwordRuleConfs = new HashMap<>();
 
         ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
         scanner.addIncludeFilter(new AssignableTypeFilter(BasePage.class));
@@ -77,6 +91,9 @@ public class ClassPathScanImplementationLookup {
         scanner.addIncludeFilter(new AssignableTypeFilter(BaseExtPage.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(BaseExtWidget.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(SSOLoginFormPanel.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(ReportletConf.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(AccountRuleConf.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(PasswordRuleConf.class));
 
         scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
             try {
@@ -105,6 +122,12 @@ public class ClassPathScanImplementationLookup {
                         previewers.add((Class<? extends AbstractBinaryPreviewer>) clazz);
                     } else if (SSOLoginFormPanel.class.isAssignableFrom(clazz)) {
                         ssoLoginFormPanels.add((Class<? extends SSOLoginFormPanel>) clazz);
+                    } else if (ReportletConf.class.isAssignableFrom(clazz)) {
+                        reportletConfs.put(clazz.getName(), (Class<? extends ReportletConf>) clazz);
+                    } else if (AccountRuleConf.class.isAssignableFrom(clazz)) {
+                        accountRuleConfs.put(clazz.getName(), (Class<? extends AccountRuleConf>) clazz);
+                    } else if (PasswordRuleConf.class.isAssignableFrom(clazz)) {
+                        passwordRuleConfs.put(clazz.getName(), (Class<? extends PasswordRuleConf>) clazz);
                     }
                 }
             } catch (Throwable t) {
@@ -128,10 +151,17 @@ public class ClassPathScanImplementationLookup {
 
         ssoLoginFormPanels = Collections.unmodifiableList(ssoLoginFormPanels);
 
+        reportletConfs = Collections.unmodifiableMap(reportletConfs);
+        accountRuleConfs = Collections.unmodifiableMap(accountRuleConfs);
+        passwordRuleConfs = Collections.unmodifiableMap(passwordRuleConfs);
+
         LOG.debug("Binary previewers found: {}", previewers);
         LOG.debug("Extension pages found: {}", extPages);
         LOG.debug("Extension widgets found: {}", extWidgets);
         LOG.debug("SSO Login pages found: {}", ssoLoginFormPanels);
+        LOG.debug("Reportlet configurations found: {}", reportletConfs);
+        LOG.debug("Account Rule configurations found: {}", accountRuleConfs);
+        LOG.debug("Password Rule configurations found: {}", passwordRuleConfs);
     }
 
     public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final String mimeType) {
@@ -152,10 +182,6 @@ public class ClassPathScanImplementationLookup {
         return pages;
     }
 
-    public List<Class<? extends AbstractBinaryPreviewer>> getPreviewerClasses() {
-        return previewers;
-    }
-
     public List<Class<? extends BaseExtPage>> getExtPageClasses() {
         return extPages;
     }
@@ -168,4 +194,16 @@ public class ClassPathScanImplementationLookup {
         return ssoLoginFormPanels;
     }
 
+    public Map<String, Class<? extends ReportletConf>> getReportletConfs() {
+        return reportletConfs;
+    }
+
+    public Map<String, Class<? extends AccountRuleConf>> getAccountRuleConfs() {
+        return accountRuleConfs;
+    }
+
+    public Map<String, Class<? extends PasswordRuleConf>> getPasswordRuleConfs() {
+        return passwordRuleConfs;
+    }
+
 }
index cb33f80..bdc9269 100644 (file)
@@ -141,8 +141,8 @@ public class NotificationDirectoryPanel
                     target.add(container);
                 } catch (SyncopeClientException e) {
                     LOG.error("While deleting object {}", model.getObject().getKey(), e);
-                    SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) ? e.getClass().
-                            getName() : e.getMessage());
+                    SyncopeConsoleSession.get().error(
+                            StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage());
                 }
                 ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
             }
index 9e9097a..3602b44 100644 (file)
  */
 package org.apache.syncope.client.console.notifications;
 
-import org.apache.syncope.client.console.events.EventCategoryPanel;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.events.EventCategoryPanel;
 import org.apache.syncope.client.console.panels.search.AbstractSearchPanel;
 import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
 import org.apache.syncope.client.console.panels.search.GroupSearchPanel;
 import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.client.console.panels.search.UserSearchPanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.LoggerRestClient;
 import org.apache.syncope.client.console.rest.NotificationRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
@@ -44,7 +43,6 @@ import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPa
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MultiPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.to.DerSchemaTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.NotificationTO;
@@ -80,6 +78,8 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
 
     private final LoggerRestClient loggerRestClient = new LoggerRestClient();
 
+    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
     /**
      * Construct.
      *
@@ -107,10 +107,10 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
 
     @Override
     protected WizardModel buildModelSteps(final NotificationWrapper modelObject, final WizardModel wizardModel) {
-        wizardModel.add(new NotificationWizardBuilder.Details(modelObject));
-        wizardModel.add(new NotificationWizardBuilder.Recipients(modelObject));
-        wizardModel.add(new NotificationWizardBuilder.Events(modelObject));
-        wizardModel.add(new NotificationWizardBuilder.Abouts(modelObject));
+        wizardModel.add(new Details(modelObject));
+        wizardModel.add(new Recipients(modelObject));
+        wizardModel.add(new Events(modelObject));
+        wizardModel.add(new Abouts(modelObject));
         return wizardModel;
     }
 
@@ -332,13 +332,8 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
 
             @Override
             protected List<String> load() {
-                Optional<JavaImplInfo> providers = SyncopeConsoleSession.get().getPlatformInfo().
-                        getJavaImplInfo(ImplementationType.RECIPIENTS_PROVIDER);
-                List<String> load = providers.isPresent()
-                        ? new ArrayList<>(providers.get().getClasses())
-                        : new ArrayList<>();
-                Collections.sort(load);
-                return load;
+                return implRestClient.list(ImplementationType.RECIPIENTS_PROVIDER).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
 
@@ -371,11 +366,11 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
                     new PropertyModel<>(modelObject, "recipientClauses")).
                     required(false).build("recipients"));
 
-            AjaxDropDownChoicePanel<String> recipientsProviderClassName = new AjaxDropDownChoicePanel<>(
-                    "recipientsProviderClassName", "recipientsProviderClassName",
-                    new PropertyModel<>(notificationTO, "recipientsProviderClassName"), false);
-            recipientsProviderClassName.setChoices(recipientProviders.getObject());
-            add(recipientsProviderClassName);
+            AjaxDropDownChoicePanel<String> recipientsProvider = new AjaxDropDownChoicePanel<>(
+                    "recipientsProvider", "recipientsProvider",
+                    new PropertyModel<>(notificationTO, "recipientsProvider"), false);
+            recipientsProvider.setChoices(recipientProviders.getObject());
+            add(recipientsProvider);
 
             AjaxCheckBoxPanel selfAsRecipient = new AjaxCheckBoxPanel("selfAsRecipient",
                     getString("selfAsRecipient"), new PropertyModel<>(notificationTO, "selfAsRecipient"));
index 33df05a..09ab57e 100644 (file)
  */
 package org.apache.syncope.client.console.pages;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
@@ -49,15 +49,14 @@ public class Audit extends BasePage {
 
         final LoggerRestClient loggerRestClient = new LoggerRestClient();
 
-        List<String> events = new ArrayList<>();
-        for (AuditLoggerName audit : loggerRestClient.listAudits()) {
-            events.add(AuditLoggerName.buildEvent(
-                    audit.getType(),
-                    audit.getCategory(),
-                    audit.getSubcategory(),
-                    audit.getEvent(),
-                    audit.getResult()));
-        }
+        List<String> events = loggerRestClient.listAudits().stream().
+                map(audit -> AuditLoggerName.buildEvent(
+                audit.getType(),
+                audit.getCategory(),
+                audit.getSubcategory(),
+                audit.getEvent(),
+                audit.getResult())).
+                collect(Collectors.toList());
 
         WebMarkupContainer content = new WebMarkupContainer("content");
         content.setOutputMarkupId(true);
@@ -89,7 +88,7 @@ public class Audit extends BasePage {
                     final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged =
                             (SelectedEventsPanel.EventSelectionChanged) event.getPayload();
 
-                    for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
+                    eventSelectionChanged.getToBeRemoved().forEach(toBeRemoved -> {
                         Pair<EventCategoryTO, AuditElements.Result> eventCategory =
                                 AuditLoggerName.parseEventCategory(toBeRemoved);
 
@@ -102,9 +101,9 @@ public class Audit extends BasePage {
                                 eventCategory.getValue());
 
                         loggerRestClient.disableAudit(auditLoggerName);
-                    }
+                    });
 
-                    for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
+                    eventSelectionChanged.getToBeAdded().forEach(toBeAdded -> {
                         Pair<EventCategoryTO, AuditElements.Result> eventCategory =
                                 AuditLoggerName.parseEventCategory(toBeAdded);
 
@@ -117,7 +116,7 @@ public class Audit extends BasePage {
                                 eventCategory.getValue());
 
                         loggerRestClient.enableAudit(auditLoggerName);
-                    }
+                    });
                 }
             }
         });
index fad2ac1..0cff36c 100644 (file)
@@ -193,6 +193,12 @@ public class BasePage extends WebPage implements IAjaxIndicatorAware {
         MetaDataRoleAuthorizationStrategy.authorize(link, WebPage.RENDER, StandardEntitlement.AUDIT_LIST);
         liContainer.add(link);
 
+        liContainer = new WebMarkupContainer(getLIContainerId("implementations"));
+        confULContainer.add(liContainer);
+        link = BookmarkablePageLinkBuilder.build("implementations", Implementations.class);
+        MetaDataRoleAuthorizationStrategy.authorize(link, WebPage.RENDER, StandardEntitlement.IMPLEMENTATION_LIST);
+        liContainer.add(link);
+
         liContainer = new WebMarkupContainer(getLIContainerId("logs"));
         confULContainer.add(liContainer);
         link = BookmarkablePageLinkBuilder.build("logs", Logs.class);
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java
new file mode 100644 (file)
index 0000000..0cd1c43
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.pages;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.panels.ImplementationDirectoryPanel;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class Implementations extends BasePage {
+
+    private static final long serialVersionUID = -4562707092152823781L;
+
+    public Implementations(final PageParameters parameters) {
+        super(parameters);
+
+        body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+
+        WebMarkupContainer content = new WebMarkupContainer("content");
+        content.setOutputMarkupId(true);
+        content.setMarkupId("implementations");
+        content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList()));
+        body.add(content);
+    }
+
+    private List<ITab> buildTabList() {
+        return Arrays.stream(ImplementationType.values()).
+                filter(type -> type != ImplementationType.JWT_SSO_PROVIDER
+                && type != ImplementationType.AUDIT_APPENDER).
+                sorted(Comparator.comparing(ImplementationType::name)).
+                map(type -> new AbstractTab(Model.of(type.name())) {
+
+            private static final long serialVersionUID = -5861786415855103549L;
+
+            @Override
+            public WebMarkupContainer getPanel(final String panelId) {
+                return new ImplementationDirectoryPanel(panelId, type, getPageReference());
+            }
+        }).collect(Collectors.toList());
+    }
+}
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java
new file mode 100644 (file)
index 0000000..60a56d1
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * 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.panels;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.ImplementationDirectoryPanel.ImplementationProvider;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
+
+public class ImplementationDirectoryPanel extends DirectoryPanel<
+        ImplementationTO, ImplementationTO, ImplementationProvider, ImplementationRestClient> {
+
+    private static final long serialVersionUID = 1868839768348072635L;
+
+    private final ImplementationType type;
+
+    public ImplementationDirectoryPanel(final String id, final ImplementationType type, final PageReference pageRef) {
+        super(id, pageRef, true);
+        this.type = type;
+
+        ImplementationTO implementation = new ImplementationTO();
+        implementation.setType(type);
+
+        disableCheckBoxes();
+
+        modal.size(Modal.Size.Large);
+        modal.addSubmitButton();
+        modal.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+            private static final long serialVersionUID = 8804221891699487139L;
+
+            @Override
+            public void onClose(final AjaxRequestTarget target) {
+                implementation.setEngine(null);
+                updateResultTable(target);
+                modal.show(false);
+            }
+        });
+        setFooterVisibility(true);
+
+        restClient = new ImplementationRestClient();
+
+        initResultTable();
+
+        ImplementationEngineTogglePanel engineTogglePanel =
+                new ImplementationEngineTogglePanel("engineTogglePanel", implementation, pageRef) {
+
+            private static final long serialVersionUID = -112426445257072782L;
+
+            @Override
+            protected void onSubmit(final ImplementationEngine engine, final AjaxRequestTarget target) {
+                implementation.setKey(null);
+                implementation.setBody(null);
+
+                target.add(ImplementationDirectoryPanel.this.modal.setContent(new ImplementationModalPanel(
+                        ImplementationDirectoryPanel.this.modal, implementation, pageRef)));
+                ImplementationDirectoryPanel.this.modal.header(
+                        new StringResourceModel("any.new", Model.of(implementation)));
+                ImplementationDirectoryPanel.this.modal.show(true);
+            }
+        };
+        addInnerObject(engineTogglePanel);
+
+        AjaxLink<Void> replaceAddLink = new AjaxLink<Void>("add") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                send(ImplementationDirectoryPanel.this, Broadcast.BREADTH,
+                        new ActionLinksTogglePanel.ActionLinkToggleCloseEventPayload(target));
+                engineTogglePanel.setHeaderLabel(target);
+                engineTogglePanel.toggle(target, true);
+            }
+        };
+        ((WebMarkupContainer) get("container:content")).addOrReplace(replaceAddLink);
+
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, StandardEntitlement.IMPLEMENTATION_CREATE);
+    }
+
+    @Override
+    protected List<IColumn<ImplementationTO, String>> getColumns() {
+        List<IColumn<ImplementationTO, String>> columns = new ArrayList<>();
+
+        columns.add(new PropertyColumn<>(new StringResourceModel("key", this), "key", "key"));
+        columns.add(new PropertyColumn<>(new StringResourceModel("engine", this), "engine", "engine"));
+
+        return columns;
+    }
+
+    @Override
+    protected ActionsPanel<ImplementationTO> getActions(final IModel<ImplementationTO> model) {
+        final ActionsPanel<ImplementationTO> panel = super.getActions(model);
+
+        panel.add(new ActionLink<ImplementationTO>() {
+
+            private static final long serialVersionUID = -7978723352517770645L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target, final ImplementationTO ignore) {
+                target.add(modal.setContent(
+                        new ImplementationModalPanel(modal, model.getObject(), pageRef)));
+                modal.header(new StringResourceModel("any.edit", Model.of(model.getObject())));
+                modal.show(true);
+            }
+        }, ActionLink.ActionType.EDIT, StandardEntitlement.IMPLEMENTATION_UPDATE);
+
+        panel.add(new ActionLink<ImplementationTO>() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target, final ImplementationTO ignore) {
+                try {
+                    restClient.delete(model.getObject().getKey());
+                    SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                    target.add(container);
+                } catch (SyncopeClientException e) {
+                    LOG.error("While deleting object {}", model.getObject().getKey(), e);
+                    SyncopeConsoleSession.get().error(
+                            StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage());
+                }
+                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+            }
+        }, ActionLink.ActionType.DELETE, StandardEntitlement.IMPLEMENTATION_DELETE, true);
+
+        return panel;
+    }
+
+    @Override
+    protected ImplementationProvider dataProvider() {
+        return new ImplementationProvider(rows);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_IMPLEMENTATION_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        return Collections.<ActionLink.ActionType>emptyList();
+    }
+
+    protected class ImplementationProvider extends DirectoryDataProvider<ImplementationTO> {
+
+        private static final long serialVersionUID = 8594921866993979224L;
+
+        private final SortableDataProviderComparator<ImplementationTO> comparator;
+
+        public ImplementationProvider(final int paginatorRows) {
+            super(paginatorRows);
+
+            setSort("key", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        @Override
+        public Iterator<ImplementationTO> iterator(final long first, final long count) {
+            List<ImplementationTO> list = restClient.list(type);
+            Collections.sort(list, comparator);
+            return list.subList((int) first, (int) first + (int) count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return restClient.list(type).size();
+        }
+
+        @Override
+        public IModel<ImplementationTO> model(final ImplementationTO implementation) {
+            return new AbstractReadOnlyModel<ImplementationTO>() {
+
+                private static final long serialVersionUID = 999513782683391483L;
+
+                @Override
+                public ImplementationTO getObject() {
+                    return implementation;
+                }
+            };
+        }
+    }
+
+}
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java
new file mode 100644 (file)
index 0000000..49819d5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.panels;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.PropertyModel;
+
+public abstract class ImplementationEngineTogglePanel extends TogglePanel<Serializable> {
+
+    private static final long serialVersionUID = -7869528596656778267L;
+
+    public ImplementationEngineTogglePanel(
+            final String id,
+            final ImplementationTO implementation,
+            final PageReference pageRef) {
+
+        super(id, pageRef);
+
+        Form<?> form = new Form<>("implementationEngineForm");
+        addInnerObject(form);
+
+        PropertyModel<ImplementationEngine> engineModel = new PropertyModel<>(implementation, "engine");
+
+        form.add(new AjaxDropDownChoicePanel<>(
+                "engine", "Engine", engineModel, false).
+                setNullValid(false).
+                setChoices(Arrays.stream(ImplementationEngine.values()).collect(Collectors.toList())).
+                setStyleSheet("form-control").
+                hideLabel());
+
+        form.add(new AjaxSubmitLink("changeit", form) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                ImplementationEngineTogglePanel.this.onSubmit(engineModel.getObject(), target);
+                target.add(form);
+                toggle(target, false);
+
+                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+            }
+        });
+
+    }
+
+    protected abstract void onSubmit(ImplementationEngine engine, AjaxRequestTarget target);
+
+    public void setHeaderLabel(final AjaxRequestTarget target) {
+        setHeader(target, getString("engine"));
+    }
+
+}
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
new file mode 100644 (file)
index 0000000..a2d4690
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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.panels;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleApplication;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.init.ConsoleInitializer;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+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.common.lib.info.JavaImplInfo;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.OnLoadHeaderItem;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.util.io.IOUtils;
+
+public class ImplementationModalPanel extends AbstractModalPanel<ImplementationTO> {
+
+    private static final long serialVersionUID = 5283548960927517342L;
+
+    private enum ViewMode {
+        JAVA_CLASS,
+        JSON_BODY,
+        GROOVY_BODY
+
+    }
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final ImplementationRestClient restClient = new ImplementationRestClient();
+
+    private final ImplementationTO implementation;
+
+    private final ViewMode viewMode;
+
+    private boolean create = false;
+
+    public ImplementationModalPanel(
+            final BaseModal<ImplementationTO> modal,
+            final ImplementationTO implementation,
+            final PageReference pageRef) {
+
+        super(modal, pageRef);
+        this.implementation = implementation;
+        this.viewMode = implementation.getEngine() == ImplementationEngine.GROOVY
+                ? ViewMode.GROOVY_BODY
+                : implementation.getType() == ImplementationType.REPORTLET
+                || implementation.getType() == ImplementationType.ACCOUNT_RULE
+                || implementation.getType() == ImplementationType.PASSWORD_RULE
+                ? ViewMode.JSON_BODY
+                : ViewMode.JAVA_CLASS;
+        this.create = implementation.getKey() == null;
+
+        add(new AjaxTextFieldPanel(
+                "key", "key", new PropertyModel<>(implementation, "key"), false).
+                addRequiredLabel().setEnabled(create));
+
+        List<String> classes = Collections.emptyList();
+        if (viewMode == ViewMode.JAVA_CLASS) {
+            Optional<JavaImplInfo> javaClasses = SyncopeConsoleSession.get().getPlatformInfo().
+                    getJavaImplInfo(implementation.getType());
+            classes = javaClasses.isPresent()
+                    ? new ArrayList<>(javaClasses.get().getClasses())
+                    : new ArrayList<>();
+        } else if (viewMode == ViewMode.JSON_BODY) {
+            ClassPathScanImplementationLookup implementationLookup =
+                    (ClassPathScanImplementationLookup) SyncopeConsoleApplication.get().
+                            getServletContext().getAttribute(ConsoleInitializer.CLASSPATH_LOOKUP);
+
+            switch (implementation.getType()) {
+                case REPORTLET:
+                    classes = implementationLookup.getReportletConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                case ACCOUNT_RULE:
+                    classes = implementationLookup.getAccountRuleConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                case PASSWORD_RULE:
+                    classes = implementationLookup.getPasswordRuleConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                default:
+            }
+        }
+        Collections.sort(classes);
+
+        AjaxDropDownChoicePanel<String> javaClass = new AjaxDropDownChoicePanel<>(
+                "javaClass", "Class", new PropertyModel<>(implementation, "body"));
+        javaClass.setNullValid(false);
+        javaClass.setChoices(classes);
+        javaClass.addRequiredLabel();
+        javaClass.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
+        javaClass.setVisible(viewMode == ViewMode.JAVA_CLASS);
+        add(javaClass);
+
+        AjaxDropDownChoicePanel<String> jsonClass = new AjaxDropDownChoicePanel<>(
+                "jsonClass", "Class", new Model<>());
+        jsonClass.setNullValid(false);
+        jsonClass.setChoices(classes);
+        jsonClass.addRequiredLabel();
+        jsonClass.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
+        jsonClass.setVisible(viewMode == ViewMode.JSON_BODY);
+        if (viewMode == ViewMode.JSON_BODY && StringUtils.isNotBlank(implementation.getBody())) {
+            try {
+                JsonNode node = MAPPER.readTree(implementation.getBody());
+                if (node.has("@class")) {
+                    jsonClass.setModelObject(node.get("@class").asText());
+                }
+            } catch (IOException e) {
+                LOG.error("Could not parse as JSON payload: {}", implementation.getBody(), e);
+            }
+        }
+        jsonClass.setReadOnly(jsonClass.getModelObject() != null);
+        add(jsonClass);
+
+        WebMarkupContainer groovyClassContainer = new WebMarkupContainer("groovyClassContainer");
+        groovyClassContainer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true);
+        groovyClassContainer.setVisible(viewMode != ViewMode.JAVA_CLASS);
+        add(groovyClassContainer);
+
+        if (StringUtils.isBlank(implementation.getBody())
+                && implementation.getEngine() == ImplementationEngine.GROOVY) {
+
+            String templateClassName = null;
+
+            switch (implementation.getType()) {
+                case REPORTLET:
+                    templateClassName = "MyReportlet";
+                    break;
+
+                case ACCOUNT_RULE:
+                    templateClassName = "MyAccountRule";
+                    break;
+
+                case PASSWORD_RULE:
+                    templateClassName = "MyPasswordRule";
+                    break;
+
+                case ITEM_TRANSFORMER:
+                    templateClassName = "MyItemTransformer";
+                    break;
+
+                case TASKJOB_DELEGATE:
+                    templateClassName = "MySchedTaskJobDelegate";
+                    break;
+
+                case RECON_FILTER_BUILDER:
+                    templateClassName = "MyReconFilterBuilder";
+                    break;
+
+                case LOGIC_ACTIONS:
+                    templateClassName = "MyLogicActions";
+                    break;
+
+                case PROPAGATION_ACTIONS:
+                    templateClassName = "MyPropagationActions";
+                    break;
+
+                case PULL_ACTIONS:
+                    templateClassName = "MyPullActions";
+                    break;
+
+                case PUSH_ACTIONS:
+                    templateClassName = "MyPushActions";
+                    break;
+
+                case PULL_CORRELATION_RULE:
+                    templateClassName = "MyPullCorrelationRule";
+                    break;
+
+                case VALIDATOR:
+                    templateClassName = "MyValidator";
+                    break;
+
+                case RECIPIENTS_PROVIDER:
+                    templateClassName = "MyRecipientsProvider";
+                    break;
+
+                default:
+            }
+
+            if (templateClassName != null) {
+                try {
+                    implementation.setBody(StringUtils.substringAfter(IOUtils.toString(getClass().
+                            getResourceAsStream(
+                                    "/org/apache/syncope/client/console/implementations/" + templateClassName
+                                    + ".groovy")),
+                            "*/\n"));
+                } catch (IOException e) {
+                    LOG.error("Could not load the expected Groovy template {} for {}",
+                            templateClassName, implementation.getType(), e);
+                }
+            }
+        }
+
+        TextArea<String> groovyClass = new TextArea<>("groovyClass", new PropertyModel<>(implementation, "body"));
+        groovyClass.setMarkupId("groovyClass").setOutputMarkupPlaceholderTag(true);
+        groovyClass.setVisible(viewMode != ViewMode.JAVA_CLASS);
+        groovyClass.setRequired(true);
+        groovyClassContainer.add(groovyClass);
+
+        jsonClass.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = 5538299138211283825L;
+
+            @Override
+            protected void onEvent(final AjaxRequestTarget target) {
+                ClassPathScanImplementationLookup implementationLookup =
+                        (ClassPathScanImplementationLookup) SyncopeConsoleApplication.get().
+                                getServletContext().getAttribute(ConsoleInitializer.CLASSPATH_LOOKUP);
+
+                Class<?> clazz = null;
+                switch (implementation.getType()) {
+                    case REPORTLET:
+                        clazz = implementationLookup.getReportletConfs().get(jsonClass.getModelObject());
+                        break;
+
+                    case ACCOUNT_RULE:
+                        clazz = implementationLookup.getAccountRuleConfs().get(jsonClass.getModelObject());
+                        break;
+
+                    case PASSWORD_RULE:
+                        clazz = implementationLookup.getPasswordRuleConfs().get(jsonClass.getModelObject());
+                        break;
+
+                    default:
+                }
+
+                if (clazz != null) {
+                    try {
+                        target.appendJavaScript("editor.getDoc().setValue('"
+                                + MAPPER.writeValueAsString(clazz.newInstance())
+                                + "');");
+                    } catch (Exception e) {
+                        LOG.error("Could not generate a value for {}", jsonClass.getModelObject(), e);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public ImplementationTO getItem() {
+        return implementation;
+    }
+
+    @Override
+    public void renderHead(final IHeaderResponse response) {
+        super.renderHead(response);
+        if (viewMode != ViewMode.JAVA_CLASS) {
+            response.render(OnLoadHeaderItem.forScript(
+                    "editor = CodeMirror.fromTextArea("
+                    + "document.getElementById('groovyClassForm').children['groovyClass'], {"
+                    + "  readOnly: false, "
+                    + "  lineNumbers: true, "
+                    + "  lineWrapping: true, "
+                    + "  matchBrackets: true,"
+                    + "  autoCloseBrackets: true,"
+                    + (viewMode == ViewMode.GROOVY_BODY ? "  mode: 'text/x-groovy'," : "")
+                    + "  autoRefresh: true"
+                    + "});"
+                    + "editor.on('change', updateTextArea);"));
+        }
+    }
+
+    @Override
+    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+        try {
+            if (create) {
+                restClient.create(implementation);
+            } else {
+                restClient.update(implementation);
+            }
+
+            modal.close(target);
+            SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+        } catch (Exception e) {
+            LOG.error("While creating or updating AttrTO", e);
+            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                    ? e.getClass().getName()
+                    : e.getMessage());
+        }
+        ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+    }
+
+}
index 85a04b4..e85a39e 100644 (file)
@@ -35,9 +35,7 @@ public class ParametersEditModalPanel extends AbstractModalPanel<AttrTO> {
 
     private final AttrTO attrTO;
 
-    private final BaseModal<AttrTO> parametersModal;
-
-    private final ConfRestClient confRestClient = new ConfRestClient();
+    private final ConfRestClient restClient = new ConfRestClient();
 
     public ParametersEditModalPanel(
             final BaseModal<AttrTO> modal,
@@ -46,7 +44,6 @@ public class ParametersEditModalPanel extends AbstractModalPanel<AttrTO> {
 
         super(modal, pageRef);
         this.attrTO = attrTO;
-        this.parametersModal = modal;
         add(new ParametersDetailsPanel("parametersDetailsPanel", getItem()));
     }
 
@@ -58,8 +55,8 @@ public class ParametersEditModalPanel extends AbstractModalPanel<AttrTO> {
     @Override
     public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
         try {
-            confRestClient.set(attrTO);
-            parametersModal.close(target);
+            restClient.set(attrTO);
+            modal.close(target);
             SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
         } catch (Exception e) {
             LOG.error("While creating or updating AttrTO", e);
index ceff741..e79c013 100644 (file)
@@ -24,21 +24,21 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Optional;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.PropertyList;
 import org.apache.syncope.client.console.init.ConsoleInitializer;
 import org.apache.syncope.client.console.init.MIMETypesLoader;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 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.MultiFieldPanel;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -61,6 +61,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
     private static final MIMETypesLoader MIME_TYPES_LOADER = (MIMETypesLoader) SyncopeConsoleApplication.get().
             getServletContext().getAttribute(ConsoleInitializer.MIMETYPES_LOADER);
 
+    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
     private final MultiFieldPanel<String> enumerationValues;
 
     private final MultiFieldPanel<String> enumerationKeys;
@@ -235,26 +237,21 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
         }
         );
 
-        IModel<List<String>> validatorsList = new LoadableDetachableModel<List<String>>() {
+        IModel<List<String>> validators = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
             @Override
             protected List<String> load() {
-                Optional<JavaImplInfo> validators = SyncopeConsoleSession.get().getPlatformInfo().
-                        getJavaImplInfo(ImplementationType.VALIDATOR);
-                List<String> load = validators.isPresent()
-                        ? new ArrayList<>(validators.get().getClasses())
-                        : new ArrayList<>();
-                Collections.sort(load);
-                return load;
+                return implRestClient.list(ImplementationType.VALIDATOR).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
-        final AjaxDropDownChoicePanel<String> validatorClass = new AjaxDropDownChoicePanel<>("validatorClass",
-                getString("validatorClass"), new PropertyModel<>(schemaTO, "validatorClass"));
-        ((DropDownChoice) validatorClass.getField()).setNullValid(true);
-        validatorClass.setChoices(validatorsList.getObject());
-        schemaForm.add(validatorClass);
+        final AjaxDropDownChoicePanel<String> validator = new AjaxDropDownChoicePanel<>("validator",
+                getString("validator"), new PropertyModel<>(schemaTO, "validator"));
+        ((DropDownChoice) validator.getField()).setNullValid(true);
+        validator.setChoices(validators.getObject());
+        schemaForm.add(validator);
 
         AutoCompleteTextField<String> mandatoryCondition = new AutoCompleteTextField<String>("mandatoryCondition") {
 
index 0c7c3dc..763422e 100644 (file)
 package org.apache.syncope.client.console.panels;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.stream.Collectors;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
@@ -34,7 +32,6 @@ import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPa
 import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.types.ImplementationType;
@@ -59,6 +56,8 @@ public class RealmDetails extends Panel {
 
     private final PolicyRestClient policyRestClient = new PolicyRestClient();
 
+    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
     private final IModel<Map<String, String>> accountPolicies = new LoadableDetachableModel<Map<String, String>>() {
 
         private static final long serialVersionUID = -2012833443695917883L;
@@ -81,19 +80,14 @@ public class RealmDetails extends Panel {
         }
     };
 
-    private final IModel<List<String>> logicActionsClasses = new LoadableDetachableModel<List<String>>() {
+    private final IModel<List<String>> logicActions = new LoadableDetachableModel<List<String>>() {
 
         private static final long serialVersionUID = 5275935387613157437L;
 
         @Override
         protected List<String> load() {
-            Optional<JavaImplInfo> actions = SyncopeConsoleSession.get().getPlatformInfo().
-                    getJavaImplInfo(ImplementationType.LOGIC_ACTIONS);
-            List<String> load = actions.isPresent()
-                    ? new ArrayList<>(actions.get().getClasses())
-                    : new ArrayList<>();
-            Collections.sort(load);
-            return load;
+            return implRestClient.list(ImplementationType.LOGIC_ACTIONS).stream().
+                    map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
 
@@ -106,7 +100,7 @@ public class RealmDetails extends Panel {
     public RealmDetails(
             final String id,
             final RealmTO realmTO,
-            final ActionsPanel<?> actions,
+            final ActionsPanel<?> actionsPanel,
             final boolean unwrapped) {
 
         super(id);
@@ -149,13 +143,13 @@ public class RealmDetails extends Panel {
         ((DropDownChoice<?>) passwordPolicy.getField()).setNullValid(true);
         container.add(passwordPolicy);
 
-        AjaxPalettePanel<String> actionsClassNames = new AjaxPalettePanel.Builder<String>().
+        AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>().
                 setAllowMoveAll(true).setAllowOrder(true).
-                build("actionsClassNames",
-                        new PropertyModel<List<String>>(realmTO, "actionsClassNames"),
-                        new ListModel<>(logicActionsClasses.getObject()));
-        actionsClassNames.setOutputMarkupId(true);
-        container.add(actionsClassNames);
+                build("actions",
+                        new PropertyModel<List<String>>(realmTO, "actions"),
+                        new ListModel<>(logicActions.getObject()));
+        actions.setOutputMarkupId(true);
+        container.add(actions);
 
         container.add(new AjaxPalettePanel.Builder<>().build("resources",
                 new PropertyModel<>(realmTO, "resources"),
@@ -165,11 +159,11 @@ public class RealmDetails extends Panel {
                 setEnabled(!SyncopeConstants.ROOT_REALM.equals(realmTO.getName())).
                 setVisible(!SyncopeConstants.ROOT_REALM.equals(realmTO.getName())));
 
-        if (actions == null) {
+        if (actionsPanel == null) {
             add(new Fragment("actions", "emptyFragment", this).setRenderBodyOnly(true));
         } else {
             Fragment fragment = new Fragment("actions", "actionsFragment", this);
-            fragment.add(actions);
+            fragment.add(actionsPanel);
             add(fragment.setRenderBodyOnly(true));
         }
     }
index a2535d9..dd89ea1 100644 (file)
@@ -75,7 +75,7 @@ public class AccountPolicyDirectoryPanel extends PolicyDirectoryPanel<AccountPol
                         ruleCompositionModal, model.getObject().getKey(), PolicyType.ACCOUNT, pageRef)));
 
                 ruleCompositionModal.header(new StringResourceModel(
-                        "policy.rule.conf", AccountPolicyDirectoryPanel.this, Model.of(model.getObject())));
+                        "policy.rules", AccountPolicyDirectoryPanel.this, Model.of(model.getObject())));
 
                 MetaDataRoleAuthorizationStrategy.authorize(
                         ruleCompositionModal.getForm(), ENABLE, StandardEntitlement.POLICY_UPDATE);
index 8e3663d..32fce97 100644 (file)
@@ -72,7 +72,7 @@ public class PasswordPolicyDirectoryPanel extends PolicyDirectoryPanel<PasswordP
                         ruleCompositionModal, model.getObject().getKey(), PolicyType.PASSWORD, pageRef)));
 
                 ruleCompositionModal.header(new StringResourceModel(
-                        "policy.rule.conf", PasswordPolicyDirectoryPanel.this, Model.of(model.getObject())));
+                        "policy.rules", PasswordPolicyDirectoryPanel.this, Model.of(model.getObject())));
 
                 MetaDataRoleAuthorizationStrategy.authorize(
                         ruleCompositionModal.getForm(), ENABLE, StandardEntitlement.POLICY_UPDATE);
index 8b06630..2b5f8d4 100644 (file)
  */
 package org.apache.syncope.client.console.policies;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -33,6 +35,7 @@ import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
@@ -44,6 +47,8 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
 import org.apache.syncope.common.lib.policy.ComposablePolicy;
 import org.apache.syncope.common.lib.policy.RuleConf;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -72,6 +77,8 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
 
     private static final long serialVersionUID = 4984337552918213290L;
 
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
     private final BaseModal<T> baseModal;
 
     private final String policy;
@@ -88,7 +95,8 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
 
         enableExitButton();
 
-        this.addNewItemPanelBuilder(new PolicyRuleWizardBuilder(policy, type, new PolicyRuleWrapper(), pageRef), true);
+        this.addNewItemPanelBuilder(
+                new PolicyRuleWizardBuilder(policy, type, new PolicyRuleWrapper(true), pageRef), true);
 
         MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, StandardEntitlement.POLICY_UPDATE);
         initResultTable();
@@ -99,7 +107,7 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
         final List<IColumn<PolicyRuleWrapper, String>> columns = new ArrayList<>();
 
         columns.add(new PropertyColumn<>(
-                new StringResourceModel("ruleConf", this), "name", "name"));
+                new StringResourceModel("rule", this), "implementationKey", "implementationKey"));
 
         columns.add(new AbstractColumn<PolicyRuleWrapper, String>(
                 new StringResourceModel("configuration", this)) {
@@ -111,7 +119,12 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
                     final Item<ICellPopulator<PolicyRuleWrapper>> cellItem,
                     final String componentId,
                     final IModel<PolicyRuleWrapper> rowModel) {
-                cellItem.add(new Label(componentId, rowModel.getObject().getConf().getClass().getName()));
+
+                if (rowModel.getObject().getConf() == null) {
+                    cellItem.add(new Label(componentId, ""));
+                } else {
+                    cellItem.add(new Label(componentId, rowModel.getObject().getConf().getClass().getName()));
+                }
             }
         });
         return columns;
@@ -131,9 +144,7 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
 
                 PolicyRuleDirectoryPanel.this.getTogglePanel().close(target);
                 send(PolicyRuleDirectoryPanel.this, Broadcast.EXACT,
-                        new AjaxWizard.EditItemActionEvent<>(
-                                new PolicyRuleWrapper().setConf(clone).setName(null),
-                                target));
+                        new AjaxWizard.EditItemActionEvent<>(new PolicyRuleWrapper(true).setConf(clone), target));
             }
         }, ActionLink.ActionType.CLONE, StandardEntitlement.POLICY_CREATE);
         panel.add(new ActionLink<PolicyRuleWrapper>() {
@@ -143,8 +154,13 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
             @Override
             public void onClick(final AjaxRequestTarget target, final PolicyRuleWrapper ignore) {
                 PolicyRuleDirectoryPanel.this.getTogglePanel().close(target);
-                send(PolicyRuleDirectoryPanel.this, Broadcast.EXACT,
-                        new AjaxWizard.EditItemActionEvent<>(model.getObject(), target));
+                if (model.getObject().getConf() == null) {
+                    SyncopeConsoleSession.get().info(getString("noConf"));
+                    ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+                } else {
+                    send(PolicyRuleDirectoryPanel.this, Broadcast.EXACT,
+                            new AjaxWizard.EditItemActionEvent<>(model.getObject(), target));
+                }
             }
         }, ActionLink.ActionType.EDIT, StandardEntitlement.POLICY_UPDATE);
         panel.add(new ActionLink<PolicyRuleWrapper>() {
@@ -214,21 +230,46 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
 
         private static final long serialVersionUID = 4725679400450513556L;
 
+        private final ImplementationRestClient implementationClient = new ImplementationRestClient();
+
         private final SortableDataProviderComparator<PolicyRuleWrapper> comparator;
 
         public PolicyRuleDataProvider(final int paginatorRows) {
             super(paginatorRows);
 
             // Default sorting
-            setSort("name", SortOrder.ASCENDING);
+            setSort("implementationKey", SortOrder.ASCENDING);
             comparator = new SortableDataProviderComparator<>(this);
         }
 
+        @SuppressWarnings("unchecked")
+        private List<PolicyRuleWrapper> getPolicyRuleWrappers(final ComposablePolicy policy) {
+            return policy.getRules().stream().map(rule -> {
+                ImplementationTO implementation = implementationClient.read(rule);
+
+                PolicyRuleWrapper wrapper = new PolicyRuleWrapper(false).
+                        setImplementationKey(implementation.getKey()).
+                        setImplementationEngine(implementation.getEngine());
+                if (implementation.getEngine() == ImplementationEngine.JAVA) {
+                    try {
+                        RuleConf ruleConf = MAPPER.readValue(implementation.getBody(), RuleConf.class);
+                        wrapper.setConf(ruleConf);
+                    } catch (Exception e) {
+                        LOG.error("During deserialization", e);
+                    }
+                }
+
+                return wrapper;
+            }).collect(Collectors.toList());
+        }
+
         @Override
         public Iterator<PolicyRuleWrapper> iterator(final long first, final long count) {
             final T actual = restClient.getPolicy(policy);
 
-            List<PolicyRuleWrapper> rules = PolicyRuleWizardBuilder.getPolicyRuleWrappers(actual);
+            List<PolicyRuleWrapper> rules = actual instanceof ComposablePolicy
+                    ? getPolicyRuleWrappers((ComposablePolicy) actual)
+                    : Collections.emptyList();
 
             Collections.sort(rules, comparator);
             return rules.subList((int) first, (int) (first + count)).iterator();
@@ -237,7 +278,9 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct
         @Override
         public long size() {
             final T actual = restClient.getPolicy(policy);
-            return PolicyRuleWizardBuilder.getPolicyRuleWrappers(actual).size();
+            return actual instanceof ComposablePolicy
+                    ? getPolicyRuleWrappers((ComposablePolicy) actual).size()
+                    : 0;
         }
 
         @Override
index 261604b..9142881 100644 (file)
@@ -21,28 +21,25 @@ package org.apache.syncope.client.console.policies;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.BeanPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 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.wizards.AjaxWizardBuilder;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.policy.AbstractPolicyTO;
-import org.apache.syncope.common.lib.policy.AccountPolicyTO;
 import org.apache.syncope.common.lib.policy.ComposablePolicy;
 import org.apache.syncope.common.lib.policy.RuleConf;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.PageReference;
-import org.apache.wicket.core.util.lang.PropertyResolver;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.wizard.WizardModel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.model.LoadableDetachableModel;
@@ -54,33 +51,7 @@ public class PolicyRuleWizardBuilder extends AjaxWizardBuilder<PolicyRuleWrapper
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
-    private static final ImplementationRestClient IMPLEMENTATION_CLIENT = new ImplementationRestClient();
-
-    @SuppressWarnings("unchecked")
-    public static List<PolicyRuleWrapper> getPolicyRuleWrappers(final AbstractPolicyTO policyTO) {
-        Object rules = PropertyResolver.getValue("rules", policyTO);
-        if (rules instanceof List) {
-            return ((List<String>) rules).stream().map(rule -> {
-                ImplementationTO implementation = IMPLEMENTATION_CLIENT.read(rule);
-
-                PolicyRuleWrapper wrapper = null;
-                if (implementation.getEngine() == ImplementationEngine.JAVA) {
-                    try {
-                        RuleConf ruleConf = MAPPER.readValue(implementation.getBody(), RuleConf.class);
-                        wrapper = new PolicyRuleWrapper().
-                                setImplementationKey(implementation.getKey()).
-                                setName(ruleConf.getName());
-                    } catch (Exception e) {
-                        LOG.error("During deserialization", e);
-                    }
-                }
-
-                return wrapper;
-            }).filter(wrapper -> wrapper != null).collect(Collectors.toList());
-        } else {
-            return null;
-        }
-    }
+    private final ImplementationRestClient implementationClient = new ImplementationRestClient();
 
     private final PolicyRestClient restClient = new PolicyRestClient();
 
@@ -91,9 +62,11 @@ public class PolicyRuleWizardBuilder extends AjaxWizardBuilder<PolicyRuleWrapper
     public PolicyRuleWizardBuilder(
             final String policy,
             final PolicyType type,
-            final PolicyRuleWrapper reportlet,
+            final PolicyRuleWrapper policyWrapper,
             final PageReference pageRef) {
-        super(reportlet, pageRef);
+
+        super(policyWrapper, pageRef);
+
         this.policy = policy;
         this.type = type;
     }
@@ -109,28 +82,19 @@ public class PolicyRuleWizardBuilder extends AjaxWizardBuilder<PolicyRuleWrapper
             throw new IllegalStateException("Non composable policy");
         }
 
-        ImplementationTO rule = new ImplementationTO();
-        rule.setKey(modelObject.getName());
-        rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(composable instanceof AccountPolicyTO
-                ? ImplementationType.ACCOUNT_RULE : ImplementationType.PASSWORD_RULE);
-        try {
-            rule.setBody(MAPPER.writeValueAsString(modelObject.getConf()));
-
-            rule = IMPLEMENTATION_CLIENT.create(rule);
-        } catch (Exception e) {
-            throw new IllegalStateException("Could not create rule", e);
+        if (modelObject.getImplementationEngine() == ImplementationEngine.JAVA) {
+            ImplementationTO rule = implementationClient.read(modelObject.getImplementationKey());
+            try {
+                rule.setBody(MAPPER.writeValueAsString(modelObject.getConf()));
+                implementationClient.update(rule);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
         }
 
-        if (!modelObject.isNew()) {
-            List<PolicyRuleWrapper> wrappers = getPolicyRuleWrappers(policyTO);
-            wrappers.removeAll(wrappers.stream().
-                    filter(wrapper -> wrapper.getName().equals(modelObject.getOldName())).collect(Collectors.toSet()));
-            composable.getRules().clear();
-            composable.getRules().addAll(wrappers.stream().
-                    map(PolicyRuleWrapper::getImplementationKey).collect(Collectors.toSet()));
+        if (modelObject.isNew()) {
+            composable.getRules().add(modelObject.getImplementationKey());
         }
-        composable.getRules().add(rule.getKey());
 
         restClient.updatePolicy(policyTO);
         return modelObject;
@@ -147,75 +111,69 @@ public class PolicyRuleWizardBuilder extends AjaxWizardBuilder<PolicyRuleWrapper
 
         private static final long serialVersionUID = -3043839139187792810L;
 
+        private final PolicyRuleWrapper rule;
+
         public Profile(final PolicyRuleWrapper rule) {
-            final AjaxTextFieldPanel name = new AjaxTextFieldPanel(
-                    "name", "rule", new PropertyModel<>(rule, "name"), false);
-            name.addRequiredLabel();
-            add(name);
+            this.rule = rule;
 
             final AjaxDropDownChoicePanel<String> conf = new AjaxDropDownChoicePanel<>(
-                    "configuration", "configuration", new PropertyModel<String>(rule, "conf") {
-
-                private static final long serialVersionUID = -6427731218492117883L;
-
-                @Override
-                public String getObject() {
-                    return rule.getConf() == null ? null : rule.getConf().getClass().getName();
-                }
-
-                @Override
-                public void setObject(final String object) {
-                    RuleConf conf = null;
+                    "rule", "rule", new PropertyModel<>(rule, "implementationKey"));
 
-                    try {
-                        conf = RuleConf.class.cast(Class.forName(object).newInstance());
-                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
-                        LOG.warn("Error retrieving reportlet configuration instance", e);
-                    }
-
-                    rule.setConf(conf);
-                }
-            });
-
-            Optional<JavaImplInfo> providers;
             List<String> choices;
             switch (type) {
                 case ACCOUNT:
-                    providers = SyncopeConsoleSession.get().getPlatformInfo().
-                            getJavaImplInfo(ImplementationType.ACCOUNT_RULE);
-                    choices = providers.isPresent()
-                            ? new ArrayList<>(providers.get().getClasses())
-                            : new ArrayList<>();
+                    choices = implementationClient.list(ImplementationType.ACCOUNT_RULE).stream().
+                            map(EntityTO::getKey).sorted().collect(Collectors.toList());
                     break;
 
                 case PASSWORD:
-                    providers = SyncopeConsoleSession.get().getPlatformInfo().
-                            getJavaImplInfo(ImplementationType.PASSWORD_RULE);
-                    choices = providers.isPresent()
-                            ? new ArrayList<>(providers.get().getClasses())
-                            : new ArrayList<>();
+                    choices = implementationClient.list(ImplementationType.PASSWORD_RULE).stream().
+                            map(EntityTO::getKey).sorted().collect(Collectors.toList());
                     break;
 
                 default:
                     choices = new ArrayList<>();
             }
 
-            Collections.<String>sort(choices);
             conf.setChoices(choices);
-
             conf.addRequiredLabel();
+            conf.setNullValid(false);
+            conf.setEnabled(rule.isNew());
+            conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -7133385027739964990L;
+
+                @Override
+                protected void onEvent(final AjaxRequestTarget target) {
+                    ImplementationTO implementation = implementationClient.read(conf.getModelObject());
+                    rule.setImplementationEngine(implementation.getEngine());
+                    if (implementation.getEngine() == ImplementationEngine.JAVA) {
+                        try {
+                            RuleConf ruleConf = MAPPER.readValue(implementation.getBody(), RuleConf.class);
+                            rule.setConf(ruleConf);
+                        } catch (Exception e) {
+                            LOG.error("During deserialization", e);
+                        }
+                    }
+                }
+            });
             add(conf);
         }
+
+        @Override
+        public void applyState() {
+            if (rule.getImplementationEngine() == ImplementationEngine.GROOVY) {
+                getWizardModel().finish();
+            }
+        }
     }
 
     public class Configuration extends WizardStep {
 
         private static final long serialVersionUID = -785981096328637758L;
 
-        private final LoadableDetachableModel<Serializable> bean;
-
         public Configuration(final PolicyRuleWrapper rule) {
-            bean = new LoadableDetachableModel<Serializable>() {
+            LoadableDetachableModel<Serializable> bean = new LoadableDetachableModel<Serializable>() {
 
                 private static final long serialVersionUID = 2092144708018739371L;
 
@@ -224,7 +182,6 @@ public class PolicyRuleWizardBuilder extends AjaxWizardBuilder<PolicyRuleWrapper
                     return rule.getConf();
                 }
             };
-
             add(new BeanPanel<>("bean", bean).setRenderBodyOnly(true));
         }
     }
index b05eabc..c8d52ea 100644 (file)
@@ -20,33 +20,30 @@ package org.apache.syncope.client.console.policies;
 
 import java.io.Serializable;
 import org.apache.syncope.common.lib.policy.RuleConf;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
 
 public class PolicyRuleWrapper implements Serializable {
 
     private static final long serialVersionUID = 2472755929742424558L;
 
-    private String implementationKey;
+    private final boolean isNew;
 
-    private String oldname;
+    private String implementationKey;
 
-    private String name;
+    private ImplementationEngine implementationEngine;
 
     private RuleConf conf;
 
-    public String getImplementationKey() {
-        return implementationKey;
+    public PolicyRuleWrapper(final boolean isNew) {
+        this.isNew = isNew;
     }
 
     public boolean isNew() {
-        return oldname == null;
-    }
-
-    public String getOldName() {
-        return this.oldname;
+        return isNew;
     }
 
-    public String getName() {
-        return this.name;
+    public String getImplementationKey() {
+        return implementationKey;
     }
 
     public PolicyRuleWrapper setImplementationKey(final String implementationKey) {
@@ -54,8 +51,12 @@ public class PolicyRuleWrapper implements Serializable {
         return this;
     }
 
-    public PolicyRuleWrapper setName(final String name) {
-        this.name = name;
+    public ImplementationEngine getImplementationEngine() {
+        return implementationEngine;
+    }
+
+    public PolicyRuleWrapper setImplementationEngine(final ImplementationEngine implementationEngine) {
+        this.implementationEngine = implementationEngine;
         return this;
     }
 
index 7cee8ab..313d869 100644 (file)
@@ -26,7 +26,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -34,6 +33,7 @@ import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.rest.SchemaRestClient;
 import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
@@ -41,7 +41,6 @@ import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.Bas
 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.MultiPanel;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -61,6 +60,12 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
 
     private static final long serialVersionUID = 5945391813567245081L;
 
+    private enum CorrelationRuleType {
+        PLAIN_ATTRIBUTES,
+        CUSTOM;
+
+    }
+
     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     private final IModel<List<CorrelationRule>> model;
@@ -83,13 +88,9 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
 
             private static final long serialVersionUID = -8168676563540297301L;
 
-            private List<CorrelationRule> rules =
-                    (policyTO.getSpecification().getCorrelationRules() == null
-                            ? Collections.<String>emptySet()
-                            : policyTO.getSpecification().getCorrelationRules().keySet()).stream().
-                            map(rule -> new CorrelationRule(
-                            rule, policyTO.getSpecification().getCorrelationRules().get(rule))).
-                            collect(Collectors.toList());
+            private List<CorrelationRule> rules = policyTO.getSpecification().getCorrelationRules().keySet().stream().
+                    map(rule -> new CorrelationRule(rule, policyTO.getSpecification().getCorrelationRules().get(rule))).
+                    collect(Collectors.toList());
 
             @Override
             public List<CorrelationRule> getObject() {
@@ -143,7 +144,9 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
 
         private static final long serialVersionUID = -4708008994320210839L;
 
-        public CorrelationRulePanel(final String id, final IModel<CorrelationRule> rule) {
+        private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
+        CorrelationRulePanel(final String id, final IModel<CorrelationRule> rule) {
             super(id);
 
             AjaxDropDownChoicePanel<String> anyType = new AjaxDropDownChoicePanel<>(
@@ -152,25 +155,21 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
                     setChoices(new AnyTypeRestClient().list());
             add(anyType);
 
-            final AjaxDropDownChoicePanel<String> ruleType = new AjaxDropDownChoicePanel<>(
-                    "ruleType", "rule.type", new PropertyModel<String>(rule.getObject(), "type"), false).
+            final AjaxDropDownChoicePanel<CorrelationRuleType> ruleType = new AjaxDropDownChoicePanel<>(
+                    "ruleType", "rule.type", new PropertyModel<CorrelationRuleType>(rule.getObject(), "type"), false).
                     setNullValid(true).
-                    setChoices(Arrays.asList("PLAIN ATTRIBUTES", "JAVA"));
+                    setChoices(Arrays.stream(CorrelationRuleType.values()).collect(Collectors.toList()));
             add(ruleType);
 
             // ---------------------------------------------------------------
-            // Java rule palette
+            // Custom rule palette
             // ---------------------------------------------------------------
-            Optional<JavaImplInfo> pullCorrelationRules = SyncopeConsoleSession.get().getPlatformInfo().
-                    getJavaImplInfo(ImplementationType.PULL_CORRELATION_RULE);
-            List<String> load = pullCorrelationRules.isPresent()
-                    ? new ArrayList<>(pullCorrelationRules.get().getClasses())
-                    : new ArrayList<>();
-            Collections.sort(load);
-            final AjaxDropDownChoicePanel<String> javaRule = new AjaxDropDownChoicePanel<>(
-                    "javaRule", "rule.java", new PropertyModel<String>(rule.getObject(), "rule")).setChoices(load);
-            javaRule.setOutputMarkupPlaceholderTag(true);
-            add(javaRule.setVisible("JAVA".equals(rule.getObject().getType())));
+            List<String> rules = implRestClient.list(ImplementationType.PULL_CORRELATION_RULE).stream().
+                    map(EntityTO::getKey).sorted().collect(Collectors.toList());
+            final AjaxDropDownChoicePanel<String> customRule = new AjaxDropDownChoicePanel<>(
+                    "customRule", "rule.custom", new PropertyModel<String>(rule.getObject(), "rule")).setChoices(rules);
+            customRule.setOutputMarkupPlaceholderTag(true);
+            add(customRule.setVisible(CorrelationRuleType.CUSTOM == rule.getObject().getType()));
             // ---------------------------------------------------------------
 
             // ---------------------------------------------------------------
@@ -245,7 +244,7 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
                 }
             });
 
-            add(jsonRule.setVisible("PLAIN ATTRIBUTES".equals(rule.getObject().getType())));
+            add(jsonRule.setVisible(CorrelationRuleType.PLAIN_ATTRIBUTES == rule.getObject().getType()));
             // ---------------------------------------------------------------
 
             ruleType.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
@@ -254,23 +253,25 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
 
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
-                    switch (ruleType.getModelObject() == null ? StringUtils.EMPTY : ruleType.getModelObject()) {
-                        case "PLAIN ATTRIBUTES":
+                    switch (ruleType.getModelObject()) {
+                        case PLAIN_ATTRIBUTES:
                             jsonRule.setVisible(true);
-                            javaRule.setVisible(false);
+                            customRule.setVisible(false);
                             jsonRule.reload(target);
                             break;
-                        case "JAVA":
+
+                        case CUSTOM:
                             jsonRule.setVisible(false);
-                            javaRule.setVisible(true);
+                            customRule.setVisible(true);
                             break;
+
                         default:
-                            javaRule.setVisible(false);
+                            customRule.setVisible(false);
                             jsonRule.setVisible(false);
 
                     }
                     target.add(jsonRule);
-                    target.add(javaRule);
+                    target.add(customRule);
                 }
             });
         }
@@ -293,25 +294,26 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
         }
     }
 
-    protected static class CorrelationRule implements Serializable {
+    private static class CorrelationRule implements Serializable {
 
         private static final long serialVersionUID = 5250228867297353011L;
 
         private String any;
 
-        private String type;
+        private CorrelationRuleType type;
 
         private String rule;
 
-        public CorrelationRule() {
+        CorrelationRule() {
             this.any = AnyTypeKind.USER.name();
-            this.type = "PLAIN ATTRIBUTES";
+            this.type = CorrelationRuleType.PLAIN_ATTRIBUTES;
             this.rule = "[]";
         }
 
-        public CorrelationRule(final String any, final String rule) {
+        CorrelationRule(final String any, final String rule) {
             this.any = any;
-            this.type = StringUtils.isEmpty(rule) || rule.trim().startsWith("[") ? "PLAIN ATTRIBUTES" : "JAVA";
+            this.type = StringUtils.isEmpty(rule) || rule.trim().startsWith("[") ? CorrelationRuleType.PLAIN_ATTRIBUTES
+                    : CorrelationRuleType.CUSTOM;
             this.rule = rule;
         }
 
@@ -319,7 +321,7 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
             return any;
         }
 
-        public String getType() {
+        public CorrelationRuleType getType() {
             return type;
         }
 
@@ -331,7 +333,7 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
             this.any = any;
         }
 
-        public void setType(final String type) {
+        public void setType(final CorrelationRuleType type) {
             this.type = type;
         }
 
index 32b81b7..4d55249 100644 (file)
@@ -63,7 +63,7 @@ public class PullPolicyDirectoryPanel extends PolicyDirectoryPanel<PullPolicyTO>
                         new PolicySpecModalPanel(model.getObject(), policySpecModal, pageRef)));
 
                 policySpecModal.header(new StringResourceModel(
-                        "policy.rule.conf", PullPolicyDirectoryPanel.this, Model.of(model.getObject())));
+                        "policy.rules", PullPolicyDirectoryPanel.this, Model.of(model.getObject())));
 
                 MetaDataRoleAuthorizationStrategy.authorize(
                         policySpecModal.getForm(), ENABLE, StandardEntitlement.POLICY_UPDATE);
index 721ab0e..667cc92 100644 (file)
  */
 package org.apache.syncope.client.console.reports;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -33,6 +35,7 @@ import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.panels.DirectoryPanel;
 import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.ReportRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
@@ -42,7 +45,9 @@ import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
@@ -68,6 +73,8 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
 
     private static final long serialVersionUID = 4984337552918213290L;
 
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
     private final BaseModal<ReportTO> baseModal;
 
     private final String report;
@@ -84,7 +91,8 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
 
         enableExitButton();
 
-        this.addNewItemPanelBuilder(new ReportletWizardBuilder(report, new ReportletWrapper(), pageRef), true);
+        this.addNewItemPanelBuilder(
+                new ReportletWizardBuilder(report, new ReportletWrapper(true), pageRef), true);
 
         MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, StandardEntitlement.REPORT_UPDATE);
         initResultTable();
@@ -95,7 +103,7 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
         final List<IColumn<ReportletWrapper, String>> columns = new ArrayList<>();
 
         columns.add(new PropertyColumn<>(
-                new StringResourceModel("reportlet", this), "name", "name"));
+                new StringResourceModel("reportlet", this), "implementationKey", "implementationKey"));
 
         columns.add(new AbstractColumn<ReportletWrapper, String>(
                 new StringResourceModel("configuration", this)) {
@@ -108,7 +116,11 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
                     final String componentId,
                     final IModel<ReportletWrapper> rowModel) {
 
-                cellItem.add(new Label(componentId, rowModel.getObject().getConf().getClass().getName()));
+                if (rowModel.getObject().getConf() == null) {
+                    cellItem.add(new Label(componentId, ""));
+                } else {
+                    cellItem.add(new Label(componentId, rowModel.getObject().getConf().getClass().getName()));
+                }
             }
         });
 
@@ -130,8 +142,7 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
 
                 send(ReportletDirectoryPanel.this, Broadcast.EXACT,
                         new AjaxWizard.EditItemActionEvent<>(
-                                new ReportletWrapper().setConf(clone).setName(null),
-                                target));
+                                new ReportletWrapper(true).setConf(clone), target));
             }
         }, ActionLink.ActionType.CLONE, StandardEntitlement.REPORT_CREATE);
         panel.add(new ActionLink<ReportletWrapper>() {
@@ -141,8 +152,12 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
             @Override
             public void onClick(final AjaxRequestTarget target, final ReportletWrapper ignore) {
                 ReportletDirectoryPanel.this.getTogglePanel().close(target);
-                send(ReportletDirectoryPanel.this, Broadcast.EXACT,
-                        new AjaxWizard.EditItemActionEvent<>(model.getObject(), target));
+                if (model.getObject().getConf() == null) {
+                    SyncopeConsoleSession.get().info(getString("noConf"));
+                } else {
+                    send(ReportletDirectoryPanel.this, Broadcast.EXACT,
+                            new AjaxWizard.EditItemActionEvent<>(model.getObject(), target));
+                }
             }
         }, ActionLink.ActionType.EDIT, StandardEntitlement.REPORT_UPDATE);
         panel.add(new ActionLink<ReportletWrapper>() {
@@ -210,21 +225,43 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
 
         private static final long serialVersionUID = 4725679400450513556L;
 
+        private final ImplementationRestClient implementationClient = new ImplementationRestClient();
+
         private final SortableDataProviderComparator<ReportletWrapper> comparator;
 
         public ReportDataProvider(final int paginatorRows) {
             super(paginatorRows);
 
             //Default sorting
-            setSort("name", SortOrder.ASCENDING);
+            setSort("implementationKey", SortOrder.ASCENDING);
             comparator = new SortableDataProviderComparator<>(this);
         }
 
+        private List<ReportletWrapper> getReportletWrappers(final ReportTO reportTO) {
+            return reportTO.getReportlets().stream().map(reportlet -> {
+                ImplementationTO implementation = implementationClient.read(reportlet);
+
+                ReportletWrapper wrapper = new ReportletWrapper(false).
+                        setImplementationKey(implementation.getKey()).
+                        setImplementationEngine(implementation.getEngine());
+                if (implementation.getEngine() == ImplementationEngine.JAVA) {
+                    try {
+                        ReportletConf reportletConf = MAPPER.readValue(implementation.getBody(), ReportletConf.class);
+                        wrapper.setConf(reportletConf);
+                    } catch (Exception e) {
+                        LOG.error("During deserialization", e);
+                    }
+                }
+
+                return wrapper;
+            }).filter(wrapper -> wrapper != null).collect(Collectors.toList());
+        }
+
         @Override
         public Iterator<ReportletWrapper> iterator(final long first, final long count) {
             final ReportTO actual = restClient.read(report);
 
-            List<ReportletWrapper> reportlets = ReportletWizardBuilder.getReportletWrappers(actual);
+            List<ReportletWrapper> reportlets = getReportletWrappers(actual);
 
             Collections.sort(reportlets, comparator);
             return reportlets.subList((int) first, (int) (first + count)).iterator();
@@ -233,7 +270,7 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
         @Override
         public long size() {
             final ReportTO actual = restClient.read(report);
-            return ReportletWizardBuilder.getReportletWrappers(actual).size();
+            return getReportletWrappers(actual).size();
         }
 
         @Override
index 0355ce6..8668103 100644 (file)
@@ -20,25 +20,22 @@ package org.apache.syncope.client.console.reports;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.BeanPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.ReportRestClient;
 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.wizards.AjaxWizardBuilder;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
-import org.apache.syncope.common.lib.report.AbstractReportletConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.wizard.WizardModel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.model.PropertyModel;
@@ -50,27 +47,7 @@ public class ReportletWizardBuilder extends AjaxWizardBuilder<ReportletWrapper>
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
-    private static final ImplementationRestClient IMPLEMENTATION_CLIENT = new ImplementationRestClient();
-
-    public static List<ReportletWrapper> getReportletWrappers(final ReportTO reportTO) {
-        return reportTO.getReportlets().stream().map(reportlet -> {
-            ImplementationTO implementation = IMPLEMENTATION_CLIENT.read(reportlet);
-
-            ReportletWrapper wrapper = null;
-            if (implementation.getEngine() == ImplementationEngine.JAVA) {
-                try {
-                    ReportletConf reportletCOnf = MAPPER.readValue(implementation.getBody(), ReportletConf.class);
-                    wrapper = new ReportletWrapper().
-                            setImplementationKey(implementation.getKey()).
-                            setName(reportletCOnf.getName());
-                } catch (Exception e) {
-                    LOG.error("During deserialization", e);
-                }
-            }
-
-            return wrapper;
-        }).filter(wrapper -> wrapper != null).collect(Collectors.toList());
-    }
+    private final ImplementationRestClient implementationClient = new ImplementationRestClient();
 
     private final ReportRestClient restClient = new ReportRestClient();
 
@@ -86,28 +63,20 @@ public class ReportletWizardBuilder extends AjaxWizardBuilder<ReportletWrapper>
 
     @Override
     protected Serializable onApplyInternal(final ReportletWrapper modelObject) {
-        ImplementationTO reportlet = new ImplementationTO();
-        reportlet.setKey(modelObject.getName());
-        reportlet.setEngine(ImplementationEngine.JAVA);
-        reportlet.setType(ImplementationType.REPORTLET);
-        try {
-            reportlet.setBody(MAPPER.writeValueAsString(modelObject.getConf()));
-
-            reportlet = IMPLEMENTATION_CLIENT.create(reportlet);
-        } catch (Exception e) {
-            throw new IllegalStateException("Could not create reportlet", e);
+        if (modelObject.getImplementationEngine() == ImplementationEngine.JAVA) {
+            ImplementationTO reportlet = implementationClient.read(modelObject.getImplementationKey());
+            try {
+                reportlet.setBody(MAPPER.writeValueAsString(modelObject.getConf()));
+                implementationClient.update(reportlet);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
         }
 
         ReportTO reportTO = restClient.read(report);
-        if (!modelObject.isNew()) {
-            List<ReportletWrapper> wrappers = getReportletWrappers(reportTO);
-            wrappers.removeAll(wrappers.stream().
-                    filter(wrapper -> wrapper.getName().equals(modelObject.getOldName())).collect(Collectors.toSet()));
-            reportTO.getReportlets().clear();
-            reportTO.getReportlets().addAll(wrappers.stream().
-                    map(ReportletWrapper::getImplementationKey).collect(Collectors.toSet()));
+        if (modelObject.isNew()) {
+            reportTO.getReportlets().add(modelObject.getImplementationKey());
         }
-        reportTO.getReportlets().add(reportlet.getKey());
 
         restClient.update(reportTO);
         return modelObject;
@@ -126,45 +95,32 @@ public class ReportletWizardBuilder extends AjaxWizardBuilder<ReportletWrapper>
         private static final long serialVersionUID = -3043839139187792810L;
 
         public Profile(final ReportletWrapper reportlet) {
-
-            final AjaxTextFieldPanel name = new AjaxTextFieldPanel(
-                    "name", "reportlet", new PropertyModel<>(reportlet, "name"), false);
-            name.addRequiredLabel();
-            name.setEnabled(true);
-            add(name);
-
             final AjaxDropDownChoicePanel<String> conf = new AjaxDropDownChoicePanel<>(
-                    "configuration", getString("configuration"), new PropertyModel<String>(reportlet, "conf") {
+                    "reportlet", getString("reportlet"), new PropertyModel<String>(reportlet, "implementationKey"));
 
-                private static final long serialVersionUID = -6427731218492117883L;
+            conf.setChoices(implementationClient.list(ImplementationType.REPORTLET).stream().
+                    map(EntityTO::getKey).sorted().collect(Collectors.toList()));
+            conf.addRequiredLabel();
+            conf.setNullValid(false);
+            conf.setEnabled(reportlet.isNew());
+            conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) {
 
-                @Override
-                public String getObject() {
-                    return reportlet.getConf() == null ? null : reportlet.getConf().getClass().getName();
-                }
+                private static final long serialVersionUID = -7133385027739964990L;
 
                 @Override
-                public void setObject(final String object) {
-                    AbstractReportletConf conf = null;
-
-                    try {
-                        conf = AbstractReportletConf.class.cast(Class.forName(object).newInstance());
-                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
-                        LOG.warn("Error retrieving reportlet configuration instance", e);
+                protected void onEvent(final AjaxRequestTarget target) {
+                    ImplementationTO implementation = implementationClient.read(conf.getModelObject());
+                    reportlet.setImplementationEngine(implementation.getEngine());
+                    if (implementation.getEngine() == ImplementationEngine.JAVA) {
+                        try {
+                            ReportletConf conf = MAPPER.readValue(implementation.getBody(), ReportletConf.class);
+                            reportlet.setConf(conf);
+                        } catch (Exception e) {
+                            LOG.error("During deserialization", e);
+                        }
                     }
-
-                    reportlet.setConf(conf);
                 }
             });
-
-            Optional<JavaImplInfo> reportlets = SyncopeConsoleSession.get().getPlatformInfo().
-                    getJavaImplInfo(ImplementationType.REPORTLET);
-            List<String> choices = reportlets.isPresent()
-                    ? new ArrayList<>(reportlets.get().getClasses())
-                    : new ArrayList<>();
-            conf.setChoices(choices);
-
-            conf.addRequiredLabel();
             add(conf);
         }
     }
@@ -183,8 +139,7 @@ public class ReportletWizardBuilder extends AjaxWizardBuilder<ReportletWrapper>
                     return reportlet.getConf();
                 }
             };
-
-            add(new BeanPanel<>("bean", bean, reportlet.getSCondWrapper(), "name", "reportletClassName").
+            add(new BeanPanel<>("bean", bean, reportlet.getSCondWrapper(), "name", "reportlet").
                     setRenderBodyOnly(true));
         }
     }
index d6d1d77..be628a7 100644 (file)
@@ -26,28 +26,29 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.panels.search.SearchClause;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
 
 public class ReportletWrapper implements Serializable {
 
     private static final long serialVersionUID = 2472755929742424558L;
 
-    private String implementationKey;
+    private final boolean isNew;
 
-    private String oldname;
+    private String implementationKey;
 
-    private String name;
+    private ImplementationEngine implementationEngine;
 
     private ReportletConf conf;
 
     private final Map<String, Pair<AbstractFiqlSearchConditionBuilder, List<SearchClause>>> scondWrapper;
 
-    public ReportletWrapper() {
-        this(null);
+    public ReportletWrapper(final boolean isNew) {
+        this.isNew = isNew;
+        this.scondWrapper = new HashMap<>();
     }
 
-    public ReportletWrapper(final String name) {
-        this.oldname = name;
-        this.scondWrapper = new HashMap<>();
+    public boolean isNew() {
+        return isNew;
     }
 
     public String getImplementationKey() {
@@ -59,20 +60,12 @@ public class ReportletWrapper implements Serializable {
         return this;
     }
 
-    public boolean isNew() {
-        return oldname == null;
-    }
-
-    public String getOldName() {
-        return this.oldname;
-    }
-
-    public String getName() {
-        return this.name;
+    public ImplementationEngine getImplementationEngine() {
+        return implementationEngine;
     }
 
-    public ReportletWrapper setName(final String name) {
-        this.name = name;
+    public ReportletWrapper setImplementationEngine(final ImplementationEngine implementationEngine) {
+        this.implementationEngine = implementationEngine;
         return this;
     }
 
index 2de2a54..106d271 100644 (file)
  */
 package org.apache.syncope.client.console.rest;
 
-import static org.apache.syncope.client.console.rest.BaseRestClient.getObject;
-import static org.apache.syncope.client.console.rest.BaseRestClient.getService;
-
+import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.rest.api.service.ImplementationService;
 
 public class ImplementationRestClient extends BaseRestClient {
 
     private static final long serialVersionUID = -4111950555473526287L;
 
+    public List<ImplementationTO> list(final ImplementationType type) {
+        return getService(ImplementationService.class).list(type);
+    }
+
     public ImplementationTO read(final String key) {
         return getService(ImplementationService.class).read(key);
     }
@@ -38,4 +41,13 @@ public class ImplementationRestClient extends BaseRestClient {
         Response response = service.create(implementation);
         return getObject(service, response.getLocation(), ImplementationTO.class);
     }
+
+    public void update(final ImplementationTO implementation) {
+        getService(ImplementationService.class).update(implementation);
+    }
+
+    public void delete(final String key) {
+        getService(ImplementationService.class).delete(key);
+    }
+
 }
index a2c48fd..5135193 100644 (file)
@@ -132,8 +132,8 @@ public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
         columns.add(new PropertyColumn<>(
                 new StringResourceModel("name", this), "name", "name"));
 
-        columns.add(new PropertyColumn<T, String>(new StringResourceModel(
-                "jobDelegateClassName", this), "jobDelegateClassName", "jobDelegateClassName") {
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("jobDelegate", this), "jobDelegate", "jobDelegate") {
 
             private static final long serialVersionUID = -3223917055078733093L;
 
index b940cf1..03e4338 100644 (file)
 package org.apache.syncope.client.console.tasks;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.rest.TaskRestClient;
 import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
@@ -35,8 +33,8 @@ import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownCho
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.to.AbstractProvisioningTaskTO;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.SchedTaskTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.PushTaskTO;
@@ -61,6 +59,8 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
 
     private final TaskRestClient taskRestClient = new TaskRestClient();
 
+    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
     private PushTaskWrapper wrapper;
 
     private CrontabPanel crontabPanel;
@@ -113,68 +113,47 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
 
         private static final long serialVersionUID = -3043839139187792810L;
 
-        private final IModel<List<String>> taskJobClasses = new LoadableDetachableModel<List<String>>() {
+        private final IModel<List<String>> taskJobDelegates = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
             @Override
             protected List<String> load() {
-                Optional<JavaImplInfo> taskJobDelegates = SyncopeConsoleSession.get().getPlatformInfo().
-                        getJavaImplInfo(ImplementationType.TASKJOB_DELEGATE);
-                List<String> load = taskJobDelegates.isPresent()
-                        ? new ArrayList<>(taskJobDelegates.get().getClasses())
-                        : new ArrayList<>();
-                Collections.sort(load);
-                return load;
+                return implRestClient.list(ImplementationType.TASKJOB_DELEGATE).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
 
-        private final IModel<List<String>> reconciliationFilterBuilderClasses =
-                new LoadableDetachableModel<List<String>>() {
+        private final IModel<List<String>> reconFilterBuilders = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
             @Override
             protected List<String> load() {
-                Optional<JavaImplInfo> reconFilterBuilders = SyncopeConsoleSession.get().getPlatformInfo().
-                        getJavaImplInfo(ImplementationType.RECON_FILTER_BUILDER);
-                List<String> load = reconFilterBuilders.isPresent()
-                        ? new ArrayList<>(reconFilterBuilders.get().getClasses())
-                        : new ArrayList<>();
-                Collections.sort(load);
-                return load;
+                return implRestClient.list(ImplementationType.RECON_FILTER_BUILDER).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
 
-        private final IModel<List<String>> pullActionsClasses = new LoadableDetachableModel<List<String>>() {
+        private final IModel<List<String>> pullActions = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
             @Override
             protected List<String> load() {
-                Optional<JavaImplInfo> pullActions = SyncopeConsoleSession.get().getPlatformInfo().
-                        getJavaImplInfo(ImplementationType.PULL_ACTIONS);
-                List<String> load = pullActions.isPresent()
-                        ? new ArrayList<>(pullActions.get().getClasses())
-                        : new ArrayList<>();
-                Collections.sort(load);
-                return load;
+                return implRestClient.list(ImplementationType.PULL_ACTIONS).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
 
-        private final IModel<List<String>> pushActionsClasses = new LoadableDetachableModel<List<String>>() {
+        private final IModel<List<String>> pushActions = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
             @Override
             protected List<String> load() {
-                Optional<JavaImplInfo> pushActions = SyncopeConsoleSession.get().getPlatformInfo().
-                        getJavaImplInfo(ImplementationType.PUSH_ACTIONS);
-                List<String> load = pushActions.isPresent()
-                        ? new ArrayList<>(pushActions.get().getClasses())
-                        : new ArrayList<>();
-                Collections.sort(load);
-                return load;
+                return implRestClient.list(ImplementationType.PUSH_ACTIONS).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
 
@@ -194,14 +173,13 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
                     false);
             add(active);
 
-            AjaxDropDownChoicePanel<String> jobDelegateClassName = new AjaxDropDownChoicePanel<>(
-                    "jobDelegateClassName", "jobDelegateClassName",
-                    new PropertyModel<>(taskTO, "jobDelegateClassName"), false);
-            jobDelegateClassName.setChoices(taskJobClasses.getObject());
-            jobDelegateClassName.addRequiredLabel();
-            jobDelegateClassName.setEnabled(taskTO.getKey() == null);
-            jobDelegateClassName.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize");
-            add(jobDelegateClassName);
+            AjaxDropDownChoicePanel<String> jobDelegate = new AjaxDropDownChoicePanel<>(
+                    "jobDelegate", "jobDelegate", new PropertyModel<>(taskTO, "jobDelegate"), false);
+            jobDelegate.setChoices(taskJobDelegates.getObject());
+            jobDelegate.addRequiredLabel();
+            jobDelegate.setEnabled(taskTO.getKey() == null);
+            jobDelegate.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize");
+            add(jobDelegate);
 
             // ------------------------------
             // Only for pull tasks
@@ -225,14 +203,14 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
             pullMode.setNullValid(!(taskTO instanceof PullTaskTO));
             pullTaskSpecifics.add(pullMode);
 
-            final AjaxDropDownChoicePanel<String> reconciliationFilterBuilderClassName = new AjaxDropDownChoicePanel<>(
-                    "reconciliationFilterBuilderClassName", "reconciliationFilterBuilderClassName",
-                    new PropertyModel<>(taskTO, "reconciliationFilterBuilderClassName"), false);
-            reconciliationFilterBuilderClassName.setChoices(reconciliationFilterBuilderClasses.getObject());
-            reconciliationFilterBuilderClassName.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize");
-            reconciliationFilterBuilderClassName.setEnabled(isFiltered);
-            reconciliationFilterBuilderClassName.setRequired(isFiltered);
-            pullTaskSpecifics.add(reconciliationFilterBuilderClassName);
+            final AjaxDropDownChoicePanel<String> reconFilterBuilder = new AjaxDropDownChoicePanel<>(
+                    "reconFilterBuilder", "reconFilterBuilder",
+                    new PropertyModel<>(taskTO, "reconFilterBuilder"), false);
+            reconFilterBuilder.setChoices(reconFilterBuilders.getObject());
+            reconFilterBuilder.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize");
+            reconFilterBuilder.setEnabled(isFiltered);
+            reconFilterBuilder.setRequired(isFiltered);
+            pullTaskSpecifics.add(reconFilterBuilder);
 
             pullMode.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 
@@ -240,11 +218,11 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
 
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
-                    reconciliationFilterBuilderClassName.setEnabled(
+                    reconFilterBuilder.setEnabled(
                             pullMode.getModelObject() == PullMode.FILTERED_RECONCILIATION);
-                    reconciliationFilterBuilderClassName.setRequired(
+                    reconFilterBuilder.setRequired(
                             pullMode.getModelObject() == PullMode.FILTERED_RECONCILIATION);
-                    target.add(reconciliationFilterBuilderClassName);
+                    target.add(reconFilterBuilder);
                 }
             });
 
@@ -285,19 +263,19 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
             add(provisioningTaskSpecifics.setRenderBodyOnly(true));
 
             if (taskTO instanceof AbstractProvisioningTaskTO) {
-                jobDelegateClassName.setEnabled(false).setVisible(false);
+                jobDelegate.setEnabled(false).setVisible(false);
             } else {
                 provisioningTaskSpecifics.setEnabled(false).setVisible(false);
             }
 
-            AjaxPalettePanel<String> actionsClassNames = new AjaxPalettePanel.Builder<String>().
+            AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>().
                     setAllowMoveAll(true).setAllowOrder(true).
-                    build("actionsClassNames",
-                            new PropertyModel<List<String>>(taskTO, "actionsClassNames"),
+                    build("actions",
+                            new PropertyModel<List<String>>(taskTO, "actions"),
                             new ListModel<>(taskTO instanceof PushTaskTO
-                                    ? pushActionsClasses.getObject() : pullActionsClasses.getObject()));
-            actionsClassNames.setOutputMarkupId(true);
-            provisioningTaskSpecifics.add(actionsClassNames);
+                                    ? pushActions.getObject() : pullActions.getObject()));
+            actions.setOutputMarkupId(true);
+            provisioningTaskSpecifics.add(actions);
 
             AjaxDropDownChoicePanel<MatchingRule> matchingRule = new AjaxDropDownChoicePanel<>(
                     "matchingRule", "matchingRule", new PropertyModel<>(taskTO, "matchingRule"), false);
index 5478c61..da5f451 100644 (file)
@@ -112,11 +112,11 @@ public class ActionLinksTogglePanel<T extends Serializable> extends TogglePanel<
         } else if (modelObject instanceof StatusBean) {
             header = ((StatusBean) modelObject).getResource();
         } else if (modelObject instanceof PolicyRuleWrapper) {
-            header = ((PolicyRuleWrapper) modelObject).getName();
+            header = ((PolicyRuleWrapper) modelObject).getImplementationKey();
         } else if (modelObject instanceof PolicyRuleWrapper) {
-            header = ((PolicyRuleWrapper) modelObject).getName();
+            header = ((PolicyRuleWrapper) modelObject).getImplementationKey();
         } else if (modelObject instanceof ReportletWrapper) {
-            header = ((ReportletWrapper) modelObject).getName();
+            header = ((ReportletWrapper) modelObject).getImplementationKey();
         } else if (modelObject instanceof JobTO) {
             header = ((JobTO) modelObject).getRefKey() == null
                     ? ((JobTO) modelObject).getRefDesc() : ((JobTO) modelObject).getRefKey();
index 6282061..6e9a892 100644 (file)
@@ -54,7 +54,7 @@ import org.apache.wicket.authroles.authorization.strategies.role.Roles;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
 import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
-import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.CheckBox;
@@ -65,7 +65,7 @@ import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.util.ListModel;
 
-public class Ownership extends WizardStep implements WizardModel.ICondition {
+public class Ownership extends WizardStep implements ICondition {
 
     private static final long serialVersionUID = 855618618337931784L;
 
index 9da914b..2c333b1 100644 (file)
@@ -63,7 +63,7 @@ import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.event.IEvent;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.wizard.IWizard;
-import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
@@ -77,7 +77,7 @@ import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.util.ListModel;
 
-public class Relationships extends WizardStep implements WizardModel.ICondition {
+public class Relationships extends WizardStep implements ICondition {
 
     private static final long serialVersionUID = 855618618337931784L;
 
index 806b87c..ccf71f2 100644 (file)
@@ -32,13 +32,13 @@ import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.ActionPermissions;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
-import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.util.ListModel;
 
-public class Resources extends WizardStep implements WizardModel.ICondition {
+public class Resources extends WizardStep implements ICondition {
 
     private static final long serialVersionUID = 552437609667518888L;
 
index 3746443..c93d6b0 100644 (file)
@@ -29,7 +29,7 @@ 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.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardModel.ICondition;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.Form;
@@ -37,9 +37,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.ResourceModel;
 
-public abstract class AbstractConnConfPanel<T extends AbstractBaseBean>
-        extends WizardStep
-        implements WizardModel.ICondition {
+public abstract class AbstractConnConfPanel<T extends AbstractBaseBean> extends WizardStep implements ICondition {
 
     private static final long serialVersionUID = -2025535531121434050L;
 
index 9b10057..1aa783f 100644 (file)
 package org.apache.syncope.client.console.wizards.resources;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.TogglePanel;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.wicket.PageReference;
@@ -44,6 +43,8 @@ public class ItemTransformersTogglePanel extends TogglePanel<Serializable> {
 
     private static final long serialVersionUID = -3195479265440591519L;
 
+    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
     private ItemTO item;
 
     public ItemTransformersTogglePanel(final WebMarkupContainer container, final PageReference pageRef) {
@@ -65,12 +66,8 @@ public class ItemTransformersTogglePanel extends TogglePanel<Serializable> {
         Form<?> form = new Form<>("form");
         addInnerObject(form);
 
-        Optional<JavaImplInfo> itemTransformers = SyncopeConsoleSession.get().getPlatformInfo().
-                getJavaImplInfo(ImplementationType.ITEM_TRANSFORMER);
-        List<String> choices = itemTransformers.isPresent()
-                ? new ArrayList<>(itemTransformers.get().getClasses())
-                : new ArrayList<>();
-        Collections.sort(choices);
+        List<String> choices = implRestClient.list(ImplementationType.ITEM_TRANSFORMER).stream().
+                map(EntityTO::getKey).sorted().collect(Collectors.toList());
 
         form.add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).setRenderer(new IChoiceRenderer<String>() {
 
@@ -109,11 +106,6 @@ public class ItemTransformersTogglePanel extends TogglePanel<Serializable> {
             @Override
             public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
                 toggle(target, false);
-
-                // [!] this is required to disable changed with close button
-                item.getTransformers().clear();
-                item.getTransformers().addAll(model.getObject());
-
                 target.add(container);
             }
 
index 9e26700..0f14284 100644 (file)
@@ -34,10 +34,6 @@ public abstract class ObjectTypeTogglePanel extends TogglePanel<Serializable> {
 
     private static final long serialVersionUID = -1366846136630731264L;
 
-    protected PropertyModel<String> typeModel;
-
-    private final Form<Object> form;
-
     ObjectTypeTogglePanel(
             final String id,
             final ResourceProvision item,
@@ -45,10 +41,10 @@ public abstract class ObjectTypeTogglePanel extends TogglePanel<Serializable> {
             final PageReference pageRef) {
         super(id, pageRef);
 
-        form = new Form<>("objectTypeForm");
+        Form<?> form = new Form<>("objectTypeForm");
         addInnerObject(form);
 
-        typeModel = new PropertyModel<>(item, "anyType");
+        PropertyModel<String> typeModel = new PropertyModel<>(item, "anyType");
 
         form.add(new AjaxDropDownChoicePanel<>(
                 "type", "type", typeModel, false).
index 4ebbfb3..ce29438 100644 (file)
@@ -37,6 +37,7 @@ 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.WizardModel.ICondition;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.model.Model;
@@ -92,7 +93,7 @@ public class ProvisionWizardBuilder extends AjaxWizardBuilder<ResourceProvision>
     /**
      * AuxClasses definition step.
      */
-    private static final class AuxClasses extends WizardStep implements WizardModel.ICondition {
+    private static final class AuxClasses extends WizardStep implements ICondition {
 
         private static final long serialVersionUID = 5315236191866427500L;
 
index 9c24f9a..52f3b0d 100644 (file)
  */
 package org.apache.syncope.client.console.wizards.resources;
 
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
 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.info.JavaImplInfo;
+import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TraceLevel;
@@ -47,19 +44,16 @@ public class ResourceDetailsPanel extends WizardStep {
 
     private static final long serialVersionUID = -7982691107029848579L;
 
-    private final IModel<List<String>> propagationActionsClasses = new LoadableDetachableModel<List<String>>() {
+    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
+    private final IModel<List<String>> propagationActions = new LoadableDetachableModel<List<String>>() {
 
         private static final long serialVersionUID = 5275935387613157437L;
 
         @Override
         protected List<String> load() {
-            Optional<JavaImplInfo> propagationActions = SyncopeConsoleSession.get().getPlatformInfo().
-                    getJavaImplInfo(ImplementationType.PROPAGATION_ACTIONS);
-            List<String> load = propagationActions.isPresent()
-                    ? new ArrayList<>(propagationActions.get().getClasses())
-                    : new ArrayList<>();
-            Collections.sort(load);
-            return load;
+            return implRestClient.list(ImplementationType.PROPAGATION_ACTIONS).stream().
+                    map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
 
@@ -98,9 +92,9 @@ public class ResourceDetailsPanel extends WizardStep {
 
         container.add(new AjaxPalettePanel.Builder<String>().
                 setAllowMoveAll(true).setAllowOrder(true).
-                build("propagationActionsClassNames",
-                        new PropertyModel<List<String>>(resourceTO, "propagationActionsClassNames"),
-                        new ListModel<>(propagationActionsClasses.getObject())).
+                build("propagationActions",
+                        new PropertyModel<List<String>>(resourceTO, "propagationActions"),
+                        new ListModel<>(propagationActions.getObject())).
                 setOutputMarkupId(true));
 
         container.add(new AjaxDropDownChoicePanel<>(
index 781a7ef..bc9a009 100644 (file)
@@ -41,6 +41,7 @@ page.topology=org.apache.syncope.client.console.topology.Topology
 page.reports=org.apache.syncope.client.console.pages.Reports
 page.workflow=org.apache.syncope.client.console.pages.Workflow
 page.audit=org.apache.syncope.client.console.pages.Audit
+page.implementations=org.apache.syncope.client.console.pages.Implementations
 page.logs=org.apache.syncope.client.console.pages.Logs
 page.securityquestions=org.apache.syncope.client.console.pages.SecurityQuestions
 page.types=org.apache.syncope.client.console.pages.Types
index 59143bf..cca9dea 100644 (file)
@@ -71,3 +71,4 @@ connectors.confirm.reload=This request is potentially dangerous for running oper
 intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships  (if applicable); for example:
 confirmGlobalLogout=Do you really want to perform global logout?
 administration=Administration
+implementations=Implementations
index 1f13919..8aadcef 100644 (file)
@@ -71,3 +71,4 @@ connectors.confirm.reload=Questa richiesta \u00e8 potenzialmente dannosa per le
 intAttrNameInfo.help=Oltre agli attributi auto-completati, \u00e8 possibile fare riferimento anche a gruppi, any object e membership (se applicabile); ad esempio:
 confirmGlobalLogout=Vuoi davvero procedere al logout globale?
 administration=Amministrazione
+implementations=Implementazioni
index b292d50..6916cf2 100644 (file)
@@ -71,3 +71,4 @@ connectors.confirm.reload=Esta requis\u00e7\u00e3o \u00e9 potencialmente perigos
 intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships  (if applicable); for example:
 confirmGlobalLogout=Do you really want to perform global logout?
 administration=Administra\u00e7\u00e3o
+implementations=Implementa\u00e7\u00f5es
index 62183d7..fc2a17a 100644 (file)
@@ -31,7 +31,7 @@ confirmUnlink=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u043
 confirmUnassign=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432?
 confirmDeprovision=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u043e\u0437\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b?
 confirmProvision=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b?
-confirmClone=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b\u003f
+confirmClone=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b?
 dropDownChoiceField.nullValid=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435
 DateTimeField$HoursValidator=\u0427\u0430\u0441\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 (1, 12)
 error=\u041e\u0448\u0438\u0431\u043a\u0430
@@ -70,3 +70,4 @@ connectors.confirm.reload=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438
 intAttrNameInfo.help=\u041f\u043e\u043c\u0438\u043c\u043e \u0430\u0432\u0442\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u044b, \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e (\u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:
 confirmGlobalLogout=Do you really want to perform global logout?
 administration=Administration
+implementations=\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyAccountRule.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyAccountRule.groovy
new file mode 100644 (file)
index 0000000..978e76d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.dao.AccountRule
+import org.apache.syncope.core.persistence.api.entity.user.User
+
+@CompileStatic
+class MyAccountRule implements AccountRule {
+  
+  void enforce(User user) {
+  }
+
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyItemTransformer.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyItemTransformer.groovy
new file mode 100644 (file)
index 0000000..fd4b5d4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.common.lib.to.EntityTO
+import org.apache.syncope.core.persistence.api.entity.Entity
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue
+import org.apache.syncope.core.persistence.api.entity.resource.Item
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer
+
+@CompileStatic
+class MyItemTransformer implements ItemTransformer {
+       
+  @Override
+  List<PlainAttrValue> beforePropagation(
+    Item item,
+    Entity entity,
+    List<PlainAttrValue> values) {
+
+    return values;
+  }
+    
+  @Override
+  List<Object> beforePull(
+    Item item,
+    EntityTO entityTO,
+    List<Object> values) {
+
+    return values;
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyLogicActions.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyLogicActions.groovy
new file mode 100644 (file)
index 0000000..df22aa2
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.common.lib.patch.AnyPatch
+import org.apache.syncope.common.lib.patch.AttrPatch
+import org.apache.syncope.common.lib.to.AnyTO
+import org.apache.syncope.common.lib.to.AttrTO
+import org.apache.syncope.core.provisioning.api.LogicActions
+
+@CompileStatic
+class MyLogicActions implements LogicActions {
+  
+  @Override
+  <A extends AnyTO> A beforeCreate(final A input) {
+    return input;
+  }
+
+  @Override
+  <M extends AnyPatch> M beforeUpdate(final M input) {
+    return input;
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPasswordRule.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPasswordRule.groovy
new file mode 100644 (file)
index 0000000..dab38ba
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.dao.PasswordRule
+import org.apache.syncope.core.persistence.api.entity.user.User
+
+@CompileStatic
+class MyPasswordRule implements PasswordRule {
+  
+  void enforce(User user) {
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy
new file mode 100644 (file)
index 0000000..6a24777
--- /dev/null
@@ -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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask
+import org.apache.syncope.core.persistence.api.entity.task.TaskExec
+import org.apache.syncope.core.provisioning.api.propagation.PropagationActions
+import org.identityconnectors.framework.common.objects.ConnectorObject
+
+@CompileStatic
+class MyPropagationActions implements PropagationActions {
+  
+  @Override
+  void before(PropagationTask task, ConnectorObject beforeObj) {
+    // do nothing
+  }
+
+  @Override
+  void onError(PropagationTask task, TaskExec execution, Exception error) {
+    // do nothing
+  }
+
+  @Override
+  void after(PropagationTask task, TaskExec execution, ConnectorObject afterObj) {
+    // do nothing
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
new file mode 100644 (file)
index 0000000..4d50971
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.common.lib.patch.AnyPatch
+import org.apache.syncope.common.lib.to.EntityTO
+import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask
+import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningActions
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport
+import org.apache.syncope.core.provisioning.api.pushpull.PullActions
+import org.identityconnectors.framework.common.objects.SyncDelta
+import org.quartz.JobExecutionException
+
+@CompileStatic
+class MyPullActions implements PullActions {
+  
+  @Override
+  SyncDelta beforeProvision(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  SyncDelta beforeAssign(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  SyncDelta beforeUnassign(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  SyncDelta beforeDeprovision(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  SyncDelta beforeUnlink(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  SyncDelta beforeLink(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  <P extends AnyPatch> SyncDelta beforeUpdate(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity,
+    P anyPatch) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  SyncDelta beforeDelete(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity) throws JobExecutionException {
+
+    return delta;
+  }
+
+  @Override
+  void after(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    EntityTO entity,
+    ProvisioningReport result) throws JobExecutionException {
+
+    // do nothing
+  }
+
+  @Override
+  IgnoreProvisionException onError(
+    ProvisioningProfile profile,
+    SyncDelta delta,
+    Exception e) throws JobExecutionException {
+
+    return null;
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullCorrelationRule.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullCorrelationRule.groovy
new file mode 100644 (file)
index 0000000..6f48a4c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond
+import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule
+import org.identityconnectors.framework.common.objects.ConnectorObject
+
+@CompileStatic
+class MyPullCorrelationRule implements PullCorrelationRule {
+
+  @Override
+  SearchCond getSearchCond(ConnectorObject connObj) {
+    
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPushActions.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPushActions.groovy
new file mode 100644 (file)
index 0000000..dad4206
--- /dev/null
@@ -0,0 +1,112 @@
+
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.entity.Entity
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile
+import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport
+import org.apache.syncope.core.provisioning.api.pushpull.PushActions
+import org.quartz.JobExecutionException
+
+@CompileStatic
+class MyPushActions implements PushActions {
+  
+  @Override 
+  Entity beforeAssign(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeProvision(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeUpdate(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeLink(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeUnlink(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeUnassign(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeDeprovision(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  Entity beforeDelete(
+    ProvisioningProfile profile,
+    Entity entity) throws JobExecutionException {
+
+    return entity;
+  }
+
+  @Override 
+  void onError(
+    ProvisioningProfile profile,
+    Entity entity,
+    ProvisioningReport result,
+    Exception error) throws JobExecutionException {
+
+    // do nothing
+  }
+
+  @Override 
+  void after(
+    ProvisioningProfile profile,
+    Entity entity,
+    ProvisioningReport result) throws JobExecutionException {
+
+    // do nothing
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyRecipientsProvider.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyRecipientsProvider.groovy
new file mode 100644 (file)
index 0000000..d118861
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator
+import org.apache.syncope.core.persistence.api.entity.Notification
+import org.apache.syncope.core.provisioning.api.notification.RecipientsProvider
+
+@CompileStatic
+class MyRecipientsProvider implements RecipientsProvider {
+  
+  @Override
+  Set<String> provideRecipients(Notification notification) {
+    return Collections.emptyList();
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyReconFilterBuilder.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyReconFilterBuilder.groovy
new file mode 100644 (file)
index 0000000..b19b88e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder
+import org.identityconnectors.framework.common.objects.filter.Filter
+
+@CompileStatic
+class MyReconFilterBuilder implements ReconFilterBuilder {
+  
+  @Override
+  Filter build() {
+    return PASS_THROUGH;
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyReportlet.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyReportlet.groovy
new file mode 100644 (file)
index 0000000..07447c2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator
+import org.apache.syncope.core.persistence.api.dao.Reportlet
+import org.xml.sax.SAXException
+
+@CompileStatic
+class MyReportlet implements Reportlet {
+  
+  @Override
+  void extract(ContentHandler handler) throws SAXException {
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MySchedTaskJobDelegate.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MySchedTaskJobDelegate.groovy
new file mode 100644 (file)
index 0000000..3356319
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate
+import org.quartz.JobExecutionContext
+import org.quartz.JobExecutionException
+
+@CompileStatic
+class MySchedTaskJobDelegate implements SchedTaskJobDelegate {
+       
+  @Override
+  void execute(String taskKey, boolean dryRun, JobExecutionContext context) throws JobExecutionException {
+   
+  }
+}
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyValidator.groovy b/client/console/src/main/resources/org/apache/syncope/client/console/implementations/MyValidator.groovy
new file mode 100644 (file)
index 0000000..b0c3e37
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue
+import org.apache.syncope.core.persistence.api.entity.PlainSchema
+
+@CompileStatic
+class MyValidator implements Validator {
+  
+  @Override
+  void setSchema(PlainSchema schema) {
+  }
+
+  @Override
+  void validate(String value, PlainAttrValue attrValue) {      
+  }
+}
index cb8bc9d..c79089d 100644 (file)
@@ -17,33 +17,30 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <head><title></title></head>
-  <body>
-    <wicket:panel>
-      <div class="form-group">
-        <span wicket:id="staticRecipients">[staticRecipients]</span>
+  <wicket:panel>
+    <div class="form-group">
+      <span wicket:id="staticRecipients">[staticRecipients]</span>
+    </div>
+    <div class="form-group form-group-inline">
+      <span wicket:id="recipients">[recipients]</span>
+    </div>
+    <div class="form-group">
+      <span wicket:id="recipientAttrName">[recipientAttrName]</span>
+    </div>
+    <div class="form-group">
+      <span wicket:id="recipientsProvider">[recipientsProvider]</span>
+    </div>
+    <div id="userFilter" class="form-group box">
+      <div id="title">
+        <span for="userNotifications"><wicket:message key="userNotifications"/></span>
       </div>
-      <div class="form-group form-group-inline">
-        <span wicket:id="recipients">[recipients]</span>
+      <div id="warning">
+        <span for="userNotificationsWarning"><wicket:message key="userNotificationsWarning"/></span>
       </div>
-      <div class="form-group">
-        <span wicket:id="recipientAttrName">[recipientAttrName]</span>
+      <div id="check">
+        <span wicket:id="selfAsRecipient">[selfAsRecipient]</span>
       </div>
-      <div class="form-group">
-        <span wicket:id="recipientsProviderClassName">[recipientsProviderClassName]</span>
-      </div>
-      <div id="userFilter" class="form-group box">
-        <div id="title">
-          <span for="userNotifications"><wicket:message key="userNotifications"/></span>
-        </div>
-        <div id="warning">
-          <span for="userNotificationsWarning"><wicket:message key="userNotificationsWarning"/></span>
-        </div>
-        <div id="check">
-          <span wicket:id="selfAsRecipient">[selfAsRecipient]</span>
-        </div>
-      </div>
-    </wicket:panel>
-  </body>
+    </div>
+  </wicket:panel>
 </html>
 
index 958509b..df81b96 100644 (file)
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 recipients=Recipients
-recipientsProviderClassName=Notification recipient provider
+recipientsProvider=Notification recipient provider
 staticRecipients=Static recipients
 selfAsRecipient=Include users matching About
 userNotifications=User notifications
index 6f39ad7..ce5b93e 100644 (file)
@@ -20,5 +20,5 @@ selfAsRecipient=Includi i soggetti
 userNotifications=Notifiche utente
 userNotificationsWarning=Non selezionare questa checkbox se gli eventi catturati non riguardano espressamente utenti
 search=Cerca destinatari
-recipientsProviderClassName=Provider destinatari notifica
+recipientsProvider=Provider destinatari notifica
 recipientAttrName=Attributo e-mail destinatari
index f26e5ed..99808bb 100644 (file)
@@ -20,5 +20,5 @@ selfAsRecipient=Incluir usu\u00e1rios relacionados Sobre
 userNotifications=Notifica\u00e7\u00f5es do usu\u00e1rio
 userNotificationsWarning=N\u00e3o selecione esta op\u00e7\u00e3o a menos que os eventos n\u00e3o s\u00e3o direcionados a usu\u00e1rios
 search=Pesquisa para os destinat\u00e1rios
-recipientsProviderClassName=Notification recipient provider
+recipientsProvider=Notification recipient provider
 recipientAttrName=Destinat\u00e1rios de e-mail para atributos
index 8c90a30..173230f 100644 (file)
@@ -21,5 +21,5 @@ selfAsRecipient=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u0443\u
 userNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
 userNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
 search=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-recipientsProviderClassName=Notification recipient provider
+recipientsProvider=Notification recipient provider
 recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
index a8887cf..55baf84 100644 (file)
@@ -110,6 +110,7 @@ under the License.
               <ul wicket:id="configurationUL" class="treeview-menu">
                 <li wicket:id="administrationLI"><a href="#" wicket:id="administration"><i class="fa fa-lock"></i><wicket:message key="administration"/></a></li>
                 <li wicket:id="auditLI"><a href="#" wicket:id="audit"><i class="fa fa-check-square-o"></i><wicket:message key="audit"/></a></li>
+                <li wicket:id="implementationsLI"><a href="#" wicket:id="implementations"><i class="fa fa-file-code-o"></i><wicket:message key="implementations"/></a></li>
                 <li wicket:id="logsLI"><a href="#" wicket:id="logs"><i class="fa fa-file-text-o"></i><wicket:message key="logs"/></a></li>
                 <li wicket:id="notificationsLI"><a href="#" wicket:id="notifications"><i class="fa fa-envelope-o"></i><wicket:message key="notifications"/></a></li>
                 <li wicket:id="parametersLI"><a href="#" wicket:id="parameters"><i class="fa fa-cog"></i><wicket:message key="parameters"/></a></li>
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Implementations.html b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Implementations.html
new file mode 100644 (file)
index 0000000..6982aeb
--- /dev/null
@@ -0,0 +1,36 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <section class="content-header">
+      <h1>&nbsp;</h1>
+      <ol class="breadcrumb">
+        <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> <wicket:message key="dashboard"></wicket:message></a></li>
+        <li class="active"><wicket:message key="configuration"/></li>
+        <li class="active"><wicket:message key="implementations"></wicket:message></li>
+      </ol>
+    </section>
+
+    <section class="content" wicket:id="content">
+      <div class="box">
+        <div class="box-body" wicket:id="tabbedPanel"/>
+      </div>
+    </section>
+  </wicket:extend>
+</html>
\ No newline at end of file
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.html
new file mode 100644 (file)
index 0000000..a0502c1
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <span wicket:id="engineTogglePanel"/>
+  </wicket:extend>
+</html>
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.properties
new file mode 100644 (file)
index 0000000..ffea34c
--- /dev/null
@@ -0,0 +1,19 @@
+# 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.
+any.edit=Edit implementation ${key}
+any.new=New ${type} implementation
+engine=Engine
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_it.properties
new file mode 100644 (file)
index 0000000..81b0549
--- /dev/null
@@ -0,0 +1,19 @@
+# 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.
+any.edit=Modifica implementazione ${key}
+any.new=Nuova implementazione di ${type}
+engine=Engine
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_pt_BR.properties
new file mode 100644 (file)
index 0000000..ffea34c
--- /dev/null
@@ -0,0 +1,19 @@
+# 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.
+any.edit=Edit implementation ${key}
+any.new=New ${type} implementation
+engine=Engine
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel_ru.properties
new file mode 100644 (file)
index 0000000..0098220
--- /dev/null
@@ -0,0 +1,20 @@
+# 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.
+#
+any.edit=Edit implementation ${key}
+any.new=New ${type} implementation
+engine=Engine
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.html
new file mode 100644 (file)
index 0000000..4094a8f
--- /dev/null
@@ -0,0 +1,32 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <div id="startAtContainer">
+      <form wicket:id="implementationEngineForm">
+        <div class="input-group">
+          <span wicket:id="engine"/>
+          <div class="input-group-addon">
+            <a wicket:id="changeit"><i class="fa fa-list-alt" alt="implementation engine icon" title="ImplementationEngine"></i></a>
+          </div>
+        </div>
+      </form>
+    </div>
+  </wicket:extend>
+</html>
\ No newline at end of file
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationModalPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ImplementationModalPanel.html
new file mode 100644 (file)
index 0000000..c181f9f
--- /dev/null
@@ -0,0 +1,62 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:head>
+    <link rel="stylesheet" type="text/css" href="webjars/codemirror/${codemirror.version}/lib/codemirror.css"/>
+
+    <script type="text/javascript">
+      var editor;
+    </script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/lib/codemirror.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/mode/groovy/groovy.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/addon/display/autorefresh.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/addon/search/search.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/addon/search/searchcursor.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/addon/edit/matchbrackets.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/addon/edit/closebrackets.js"></script>
+    <script type="text/javascript">
+      function updateTextArea(editor) {
+        document.getElementById("groovyClassForm").children["groovyClass"].value = editor.getValue();
+      }
+    </script>
+    <style>
+      .w_content_3 {
+        padding: 0;
+        color: #333333;
+        font-family: Verdana,Tahoma,sans-serif;
+        font-size: 100%;
+        border: 1px solid #BBBBBB;
+        margin-top: 5px;
+      }
+    </style>
+  </wicket:head>
+  <wicket:extend>
+    <div class="form-group">
+      <span wicket:id="key"></span>
+      <span wicket:id="javaClass"></span>
+      <span wicket:id="jsonClass"></span>
+      <div wicket:id="groovyClassContainer">
+        <div class="w_content_3" id="groovyClassForm">
+          <textarea wicket:id="groovyClass" name="groovyClass" style="width: 100%; height: 350px;">
+          </textarea>
+        </div>
+      </div>
+    </div>
+  </wicket:extend>
+</html>
index 0a04bee..d4fff44 100644 (file)
@@ -55,7 +55,7 @@ under the License.
       </div>
 
       <div class="form-group">
-        <span wicket:id="validatorClass">[validatorClass]</span>
+        <span wicket:id="validator">[validator]</span>
       </div>
 
       <div class="form-group">
index 512fc01..b3f99bb 100644 (file)
@@ -22,7 +22,7 @@ uniqueConstraint=Unique
 multivalue=Multivalue
 multivalueAndUniqueConstr.validation='Multivalue' and 'Unique constraint' options can't be both checked
 type=Type
-validatorClass=Validator class
+validator=Validator
 conversionPattern=Conversion pattern
 action=Action
 edit_attribute=Edit attribute
index 4896749..bd4766b 100644 (file)
@@ -20,7 +20,7 @@ enumerationValues= Valori enumeration
 enumerationKeys= Label enumeration
 multivalue=Multivalore
 type=Tipo
-validatorClass=Validatore
+validator=Validatore
 conversionPattern=Conversion pattern
 action=Azione
 edit_attribute=Modifica attributo
index beae751..f607f99 100644 (file)
@@ -22,7 +22,7 @@ uniqueConstraint=\u00danico
 multivalue=Multivalorado
 multivalueAndUniqueConstr.validation=As op\u00e7\u00f5es 'Multivalorado' e 'Restri\u00e7\u00e3o \u00fanica' n\u00e3o podem serem ambas selecionadas
 type=Tipo
-validatorClass=Classe de Valida\u00e7\u00e3o
+validator=Valida\u00e7\u00e3o
 conversionPattern=Padr\u00e3o de Convers\u00e3o
 action=A\u00e7\u00e3o
 edit_attribute=Editar Atributo
index ffe47a4..b190c79 100644 (file)
 # specific language governing permissions and limitations
 # under the License.
 #
-# required_alert=Все поля обязательны для заполнения.
+# required_alert=\u00d0\u0092\u00d1\u0081\u00d0\u00b5 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008f \u00d0\u00be\u00d0\u00b1\u00d1\u008f\u00d0\u00b7\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c\u00d0\u00bd\u00d1\u008b \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00b7\u00d0\u00b0\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d0\u00bd\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f.
 required_alert=\u0412\u0441\u0435 \u043f\u043e\u043b\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.
-# mandatoryCondition=Обязательный
+# mandatoryCondition=\u00d0\u009e\u00d0\u00b1\u00d1\u008f\u00d0\u00b7\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c\u00d0\u00bd\u00d1\u008b\u00d0\u00b9
 mandatoryCondition=\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439
-# enumerationValues=Перечень значений
+# enumerationValues=\u00d0\u009f\u00d0\u00b5\u00d1\u0080\u00d0\u00b5\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d1\u008c \u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b9
 enumerationValues=\u041f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439
-# enumerationKeys=Перечень наименований
+# enumerationKeys=\u00d0\u009f\u00d0\u00b5\u00d1\u0080\u00d0\u00b5\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d1\u008c \u00d0\u00bd\u00d0\u00b0\u00d0\u00b8\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b9
 enumerationKeys=\u041f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0439
-# uniqueConstraint=Уникальный
+# uniqueConstraint=\u00d0\u00a3\u00d0\u00bd\u00d0\u00b8\u00d0\u00ba\u00d0\u00b0\u00d0\u00bb\u00d1\u008c\u00d0\u00bd\u00d1\u008b\u00d0\u00b9
 uniqueConstraint=\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439
-# multivalue=Множественные значения
+# multivalue=\u00d0\u009c\u00d0\u00bd\u00d0\u00be\u00d0\u00b6\u00d0\u00b5\u00d1\u0081\u00d1\u0082\u00d0\u00b2\u00d0\u00b5\u00d0\u00bd\u00d0\u00bd\u00d1\u008b\u00d0\u00b5 \u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 multivalue=\u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f
-# multivalueAndUniqueConstr.validation=Свойства 'Множественные значения' и 'Уникальный' не могут использоваться одновременно
+# multivalueAndUniqueConstr.validation=\u00d0\u00a1\u00d0\u00b2\u00d0\u00be\u00d0\u00b9\u00d1\u0081\u00d1\u0082\u00d0\u00b2\u00d0\u00b0 '\u00d0\u009c\u00d0\u00bd\u00d0\u00be\u00d0\u00b6\u00d0\u00b5\u00d1\u0081\u00d1\u0082\u00d0\u00b2\u00d0\u00b5\u00d0\u00bd\u00d0\u00bd\u00d1\u008b\u00d0\u00b5 \u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f' \u00d0\u00b8 '\u00d0\u00a3\u00d0\u00bd\u00d0\u00b8\u00d0\u00ba\u00d0\u00b0\u00d0\u00bb\u00d1\u008c\u00d0\u00bd\u00d1\u008b\u00d0\u00b9' \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bc\u00d0\u00be\u00d0\u00b3\u00d1\u0083\u00d1\u0082 \u00d0\u00b8\u00d1\u0081\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d1\u008c\u00d1\u0081\u00d1\u008f \u00d0\u00be\u00d0\u00b4\u00d0\u00bd\u00d0\u00be\u00d0\u00b2\u00d1\u0080\u00d0\u00b5\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00bd\u00d0\u00be
 multivalueAndUniqueConstr.validation=\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 '\u041c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f' \u0438 '\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439' \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e
-# type=Тип
+# type=\u00d0\u00a2\u00d0\u00b8\u00d0\u00bf
 type=\u0422\u0438\u043f
-# validatorClass=Класс валидатора
-validatorClass=\u041a\u043b\u0430\u0441\u0441 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430
-# conversionPattern=Шаблон преобразования
+# validatorClass=\u00d0\u009a\u00d0\u00bb\u00d0\u00b0\u00d1\u0081\u00d1\u0081 \u00d0\u00b2\u00d0\u00b0\u00d0\u00bb\u00d0\u00b8\u00d0\u00b4\u00d0\u00b0\u00d1\u0082\u00d0\u00be\u00d1\u0080\u00d0\u00b0
+validator=\u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430
+# conversionPattern=\u00d0\u00a8\u00d0\u00b0\u00d0\u00b1\u00d0\u00bb\u00d0\u00be\u00d0\u00bd \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00be\u00d0\u00b1\u00d1\u0080\u00d0\u00b0\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 conversionPattern=\u0428\u0430\u0431\u043b\u043e\u043d \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f
-# action=Действие
+# action=\u00d0\u0094\u00d0\u00b5\u00d0\u00b9\u00d1\u0081\u00d1\u0082\u00d0\u00b2\u00d0\u00b8\u00d0\u00b5
 action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
-# edit_attribute=Изменить атрибут
+# edit_attribute=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00b0\u00d1\u0082\u00d1\u0080\u00d0\u00b8\u00d0\u00b1\u00d1\u0083\u00d1\u0082
 edit_attribute=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442
-# title=Атрибут
+# title=\u00d0\u0090\u00d1\u0082\u00d1\u0080\u00d0\u00b8\u00d0\u00b1\u00d1\u0083\u00d1\u0082
 title=\u0410\u0442\u0440\u0438\u0431\u0443\u0442
-# readonly=Только чтение
+# readonly=\u00d0\u00a2\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00ba\u00d0\u00be \u00d1\u0087\u00d1\u0082\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 readonly=\u0422\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u0435\u043d\u0438\u0435
-# secretKey=Ключ шифрования
+# secretKey=\u00d0\u009a\u00d0\u00bb\u00d1\u008e\u00d1\u0087 \u00d1\u0088\u00d0\u00b8\u00d1\u0084\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 secretKey=\u041a\u043b\u044e\u0447 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f
-# cipherAlgorithm=Алгоритм шифрования
+# cipherAlgorithm=\u00d0\u0090\u00d0\u00bb\u00d0\u00b3\u00d0\u00be\u00d1\u0080\u00d0\u00b8\u00d1\u0082\u00d0\u00bc \u00d1\u0088\u00d0\u00b8\u00d1\u0084\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 cipherAlgorithm=\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f
-# mimeType=Тип MIME
+# mimeType=\u00d0\u00a2\u00d0\u00b8\u00d0\u00bf MIME
 mimeType=\u0422\u0438\u043f MIME
index 3b9448c..b106229 100644 (file)
@@ -34,7 +34,7 @@ under the License.
         <span wicket:id="passwordPolicy">[passwordPolicy]</span>
       </div>
       <div class="form-group form-palette">
-        <span wicket:id="actionsClassNames">[actionsClassNames]</span>
+        <span wicket:id="actions">[actions]</span>
       </div>
       <div class="form-group form-palette">
         <span wicket:id="resources">[resources]</span>
index 478f1c9..67a7bcb 100644 (file)
@@ -18,5 +18,5 @@
 fullPath=\u041f\u0443\u0442\u044c
 accountPolicy=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439
 passwordPolicy=\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043f\u0430\u0440\u043e\u043b\u0435\u0439
-actionsClassNames=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f
+actions=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f
 resources=\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b
index 462153d..be212f8 100644 (file)
@@ -22,8 +22,9 @@ maxAuthenticationAttempts=Max Authentication Attempts
 propagateSuspension=Propagate Suspension
 historyLength=History Length
 allowNullPassword=Allow Null Password
-policy.rule.conf=Policy '${description}' Rule Configuration
+policy.rules=${description} Rules
 any.edit=Edit ${description}
 any.new=New Policy
 any.finish=Submit ${description}
 any.cancel=Cancel ${description}
+compose.title=rules
index 2175135..9a00b8d 100644 (file)
@@ -22,8 +22,9 @@ maxAuthenticationAttempts=Numero Massimo Tentativi Authenticazione
 propagateSuspension=Propagare Sospensione
 historyLength=Lunghezza Storico
 allowNullPassword=Permetti Password Nulla
-policy.rule.conf=Configurazione Regola Policy '${description}'
+policy.rules=Configurazione Regole di ${description}
 any.edit=Modifica ${description}
 any.new=Nuova Policy
 any.finish=Invia ${description}
 any.cancel=Annulla ${description}
+compose.title=regole
index 462153d..be212f8 100644 (file)
@@ -22,8 +22,9 @@ maxAuthenticationAttempts=Max Authentication Attempts
 propagateSuspension=Propagate Suspension
 historyLength=History Length
 allowNullPassword=Allow Null Password
-policy.rule.conf=Policy '${description}' Rule Configuration
+policy.rules=${description} Rules
 any.edit=Edit ${description}
 any.new=New Policy
 any.finish=Submit ${description}
 any.cancel=Cancel ${description}
+compose.title=rules
index c16b09b..afbd430 100644 (file)
@@ -23,8 +23,9 @@ maxAuthenticationAttempts=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c
 propagateSuspension=\u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435
 historyLength=\u0420\u0430\u0437\u043c\u0435\u0440 \u0438\u0441\u0442\u043e\u0440\u0438\u0438
 allowNullPassword=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u043e\u0439 \u043f\u0430\u0440\u043e\u043b\u044c
-policy.rule.conf=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u0430\u0432\u0438\u043b \u0434\u043b\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 '${description}'
+policy.rules=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u0430\u0432\u0438\u043b \u0434\u043b\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 '${description}'
 any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c ${description}
 any.new=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443
 any.finish=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c ${description}
 any.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c ${description}
+compose.title=rules
index d55a533..8ac598c 100644 (file)
@@ -14,5 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-ruleConf=Rule
-configuration=Type
+rule=Rule
+configuration=Configuration
+noConf=No configuration available
index 1ee8471..abd8c4e 100644 (file)
@@ -14,5 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-ruleConf=Regola
-configuration=Tipo
+rule=Regola
+configuration=Configurazione
+noConf=Nessuna configurazione
index d55a533..91afb1b 100644 (file)
@@ -14,5 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-ruleConf=Rule
-configuration=Type
+rule=Rule
+configuration=Configura\u00e7\u00e3o
+noConf=Nenhuma configura\u00e7\u00e3o dispon\u00edvel
index ccd4f62..330887f 100644 (file)
@@ -15,5 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-ruleConf=\u041f\u0440\u0430\u0432\u0438\u043b\u043e
-configuration=\u0422\u0438\u043f
+rule=\u041f\u0440\u0430\u0432\u0438\u043b\u043e
+configuration=\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f
+noConf=No configuration available
index 5ce9540..4acf4db 100644 (file)
@@ -19,10 +19,7 @@ under the License.
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:panel>
     <div class="form-group">
-      <span wicket:id="name"/>
-    </div>
-    <div class="form-group">
-      <span wicket:id="configuration"/>
+      <span wicket:id="rule"/>
     </div>
   </wicket:panel>
 </html>
index eafcadb..d514604 100644 (file)
@@ -25,7 +25,7 @@ under the License.
       <span wicket:id="ruleType"/>
     </div>
     <div class="form-group">
-      <span wicket:id="javaRule"/>
+      <span wicket:id="customRule"/>
       <span wicket:id="jsonRule"/>
     </div>
   </wicket:panel>
index a1bc5cf..1c6b31c 100644 (file)
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-rule.java=Java Class
+rule.custom=Custom
 rule.json=Plain attributes
 rule.type=Rule Type
-JSON=Plain attributes
-JAVA=Java Class
 any.type=Applies to
 correlationRules=Correlation Rules
 conflictResolutionAction=Conflict Resolution Action
index 0b329a8..040e8fd 100644 (file)
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-rule.java=Classe Java
+rule.custom=Custom
 rule.json=Attributi
 rule.type=Tipo Regola
-JSON=Attributi
-JAVA=Classe Java
 any.type=Applicata a
 correlationRules=Regole di Correlazione
 conflictResolutionAction=Azione di Risoluzione Conflitti
index a1bc5cf..1c6b31c 100644 (file)
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-rule.java=Java Class
+rule.custom=Custom
 rule.json=Plain attributes
 rule.type=Rule Type
-JSON=Plain attributes
-JAVA=Java Class
 any.type=Applies to
 correlationRules=Correlation Rules
 conflictResolutionAction=Conflict Resolution Action
index f560ce3..8d35548 100644 (file)
 # specific language governing permissions and limitations
 # under the License.
 #
-rule.java=\u041a\u043b\u0430\u0441\u0441 Java
+rule.custom=Custom
 rule.json=\u041f\u0440\u0430\u0432\u0438\u043b\u043e JSON
 rule.type=\u0422\u0438\u043f \u043f\u0440\u0430\u0432\u0438\u043b
-JSON=\u041f\u0440\u0430\u0432\u0438\u043b\u043e JSON
-JAVA=\u041a\u043b\u0430\u0441\u0441 Java
 any.type=\u041e\u0431\u044a\u0435\u043a\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438
 correlationRules=\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u0438
 conflictResolutionAction=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432
index 15ea904..f075681 100644 (file)
@@ -17,3 +17,4 @@
 reportlet=\u041f\u0430\u043d\u0435\u043b\u044c \u043e\u0442\u0447\u0435\u0442\u0430
 profile=\u041f\u0440\u043e\u0444\u0438\u043b\u044c
 configuration=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f
+noConf=No configuration available
index 20ec555..39e019b 100644 (file)
@@ -18,7 +18,6 @@ under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:panel>
-    <div class="form-group"><span wicket:id="name">[name]</span></div>
-    <div class="form-group"><span wicket:id="configuration">[configuration]</span></div>
+    <div class="form-group"><span wicket:id="reportlet">[reportlet]</span></div>
   </wicket:panel>
 </html>
index 1226b8c..a14b3f6 100644 (file)
@@ -17,7 +17,7 @@
 name=Name
 description=Description
 destinationRealm=Destination Realm
-jobDelegateClassName=Job Delegate
+jobDelegate=Job Delegate
 lastExec=Last execution
 nextExec=Next execution
 active=Active
@@ -27,6 +27,6 @@ any.new=New task
 any.finish=Submit ${name}
 any.cancel=Cancel ${name}
 pullMode=Pull Mode
-reconciliationFilterBuilderClassName=Reconciliation Filter Builder
-actionsClassNames=Actions
+reconFilterBuilder=Reconciliation Filter Builder
+actions=Actions
 sourceRealm=Source Realm
index 5341c88..960b17a 100644 (file)
@@ -17,7 +17,7 @@
 name=Nome
 description=Descrizione
 destinationRealm=Realm di destinazione
-jobDelegateClassName=JobJob Delegate
+jobDelegate=JobJob Delegate
 lastExec=Ultima esecuszione
 nextExec=Prossima esecuzione
 active=Attivo
@@ -27,6 +27,6 @@ any.new=Nuovo Task
 any.finish=Invia ${name}
 any.cancel=Annulla ${name}
 pullMode=Pull Mode
-reconciliationFilterBuilderClassName=Reconciliation Filter Builder
-actionsClassNames=Actions
+reconFilterBuilder=Reconciliation Filter Builder
+actions=Actions
 sourceRealm=Realm sorgente
index 1226b8c..a14b3f6 100644 (file)
@@ -17,7 +17,7 @@
 name=Name
 description=Description
 destinationRealm=Destination Realm
-jobDelegateClassName=Job Delegate
+jobDelegate=Job Delegate
 lastExec=Last execution
 nextExec=Next execution
 active=Active
@@ -27,6 +27,6 @@ any.new=New task
 any.finish=Submit ${name}
 any.cancel=Cancel ${name}
 pullMode=Pull Mode
-reconciliationFilterBuilderClassName=Reconciliation Filter Builder
-actionsClassNames=Actions
+reconFilterBuilder=Reconciliation Filter Builder
+actions=Actions
 sourceRealm=Source Realm
index 103731f..9339ef7 100644 (file)
@@ -20,8 +20,7 @@ name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435
 description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435
 # destinationRealm=\u00d0\u009e\u00d0\u00b1\u00d0\u00bb\u00d0\u00b0\u00d1\u0081\u00d1\u0082\u00d1\u008c \u00d0\u00b4\u00d0\u00b5\u00d0\u00b9\u00d1\u0081\u00d1\u0082\u00d0\u00b2\u00d0\u00b8\u00d1\u008f
 destinationRealm=\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f
-# jobDelegateClassName=\u00d0\u009d\u00d0\u00b0\u00d0\u00b7\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00ba\u00d0\u00bb\u00d0\u00b0\u00d1\u0081\u00d1\u0081\u00d0\u00b0
-jobDelegateClassName=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430
+jobDelegate=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430
 # lastExec=\u00d0\u009f\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d1\u008b\u00d0\u00b4\u00d1\u0083\u00d1\u0089\u00d0\u00b8\u00d0\u00b9 \u00d0\u00b7\u00d0\u00b0\u00d0\u00bf\u00d1\u0083\u00d1\u0081\u00d0\u00ba
 lastExec=\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a
 # nextExec=\u00d0\u00a1\u00d0\u00bb\u00d0\u00b5\u00d0\u00b4\u00d1\u0083\u00d1\u008e\u00d1\u0089\u00d0\u00b8\u00d0\u00b9 \u00d0\u00b7\u00d0\u00b0\u00d0\u00bf\u00d1\u0083\u00d1\u0081\u00d0\u00ba
@@ -39,8 +38,6 @@ any.finish=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c ${name}
 any.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c ${name}
 # pullMode=\u00d0\u00a0\u00d0\u00b5\u00d0\u00b6\u00d0\u00b8\u00d0\u00bc \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f \u00d0\u00b4\u00d0\u00b0\u00d0\u00bd\u00d0\u00bd\u00d1\u008b\u00d1\u0085
 pullMode=\u0420\u0435\u0436\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445
-# reconciliationFilterBuilderClassName=\u00d0\u00a4\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080 \u00d1\u0080\u00d0\u00b5\u00d0\u00ba\u00d0\u00be\u00d0\u00bd\u00d1\u0081\u00d0\u00b8\u00d0\u00bb\u00d0\u00b8\u00d0\u00b0\u00d1\u0086\u00d0\u00b8\u00d0\u00b8
-reconciliationFilterBuilderClassName=\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u0435\u043a\u043e\u043d\u0441\u0438\u043b\u0438\u0430\u0446\u0438\u0438
-# actionsClassNames=\u00d0\u0094\u00d0\u00b5\u00d0\u00b9\u00d1\u0081\u00d1\u0082\u00d0\u00b2\u00d0\u00b8\u00d1\u008f
-actionsClassNames=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f
+reconFilterBuilder=\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u0435\u043a\u043e\u043d\u0441\u0438\u043b\u0438\u0430\u0446\u0438\u0438
+actions=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f
 sourceRealm=Source Realm
index 17b1e42..d45da13 100644 (file)
@@ -22,12 +22,12 @@ under the License.
     <div class="form-group"><span wicket:id="description">[anyKey]</span></div>
     <div class="form-group"><span wicket:id="active">[active]</span></div>
 
-    <div class="form-group"><span wicket:id="jobDelegateClassName">[jobDelegateClassName]</span></div>
+    <div class="form-group"><span wicket:id="jobDelegate">[jobDelegate]</span></div>
 
     <span wicket:id="pullTaskSpecifics">
       <div class="form-group"><span wicket:id="destinationRealm">[destinationRealm]</span></div>
       <div class="form-group"><span wicket:id="pullMode">[pullMode]</span></div>
-      <div class="form-group"><span wicket:id="reconciliationFilterBuilderClassName">[filter]</span></div>
+      <div class="form-group"><span wicket:id="reconFilterBuilder">[filter]</span></div>
     </span>      
 
     <span wicket:id="pushTaskSpecifics">
@@ -36,7 +36,7 @@ under the License.
 
     <span wicket:id="provisioningTaskSpecifics">
       <div class="form-group form-palette">
-        <span wicket:id="actionsClassNames">[actionsClassNames]</span>
+        <span wicket:id="actions">[actions]</span>
       </div>
       <div class="form-group"><span wicket:id="matchingRule">[matchingRule]</span></div>
       <div class="form-group"><span wicket:id="unmatchingRule">[unmatchingRule]</span></div>
index 6c7362a..3b79aad 100644 (file)
@@ -17,7 +17,7 @@
 #
 name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435
 description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435
-jobDelegateClassName=\u041a\u043b\u0430\u0441\u0441
+jobDelegate=\u041a\u043b\u0430\u0441\u0441
 matchingRule=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438
 unmatchingRule=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0438 \u043d\u0435\u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438
 performCreate=\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435
index 2aa2522..c730e84 100644 (file)
@@ -40,7 +40,7 @@ under the License.
       </div>
 
       <div class="form-group form-palette">
-        <span wicket:id="propagationActionsClassNames">[propagationActionsClassNames]</span>
+        <span wicket:id="propagationActions">[propagationActions]</span>
       </div>
 
       <div class="form-group">
index 663879d..5e588e5 100644 (file)
@@ -19,7 +19,7 @@ connector=Connector
 enforceMandatoryCondition=Enforce mandatory condition
 propagationPriority=Propagation priority
 randomPwdIfNotProvided=Generate random passwords when missing
-propagationActionsClassNames=Propagation Actions
+propagationActions=Propagation Actions
 createTraceLevel=Propagation: create trace level
 updateTraceLevel=Propagation: update trace level
 deleteTraceLevel=Propagation: delete trace level
index acfbcd7..33422f1 100644 (file)
@@ -19,7 +19,7 @@ connector=Connettore
 enforceMandatoryCondition=Abilita mandatory condition
 propagationPriority=Priorit\u00e0 in propagazione
 randomPwdIfNotProvided=Genera password casuali se mancanti
-propagationActionsClassNames=Azioni di Propagazione
+propagationActions=Azioni di Propagazione
 createTraceLevel=Propagazione: tracciamento creazione
 updateTraceLevel=Propagazione: tracciamento aggiornamento
 deleteTraceLevel=Propagazione: tracciamento rimozione
index ab910a4..d2c7119 100644 (file)
@@ -19,7 +19,7 @@ connector=Conector
 enforceMandatoryCondition=Aplicar condi\u00e7\u00e3o obrigat\u00f3ria
 propagationPriority=Prioridade de propaga\u00e7\u00e3o
 randomPwdIfNotProvided=Gerar senhas aleat\u00f3rias quando n\u00e3o houver
-propagationActionsClassNames=A\u00e7\u00f5es de Propaga\u00e7\u00e3o
+propagationActions=A\u00e7\u00f5es de Propaga\u00e7\u00e3o
 createTraceLevel=Propagation: create trace level
 updateTraceLevel=Propagation: update trace level
 deleteTraceLevel=Propagation: delete trace level
index 79379af..2340913 100644 (file)
@@ -20,7 +20,7 @@ connector=\u041a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440
 enforceMandatoryCondition=\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 (\u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e)
 propagationPriority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439
 randomPwdIfNotProvided=\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0435 \u0437\u0430\u0434\u0430\u043d
-propagationActionsClassNames=\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f
+propagationActions=\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f
 createTraceLevel=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e
 updateTraceLevel=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044e
 deleteTraceLevel=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e
index ce67f46..8b3403b 100644 (file)
@@ -21,7 +21,6 @@ package org.apache.syncope.common.lib.report;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.ArrayList;
 import java.util.List;
-
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlEnum;
index 4568e36..fc17702 100644 (file)
@@ -43,7 +43,7 @@ public class PlainSchemaTO extends AbstractSchemaTO {
 
     private String conversionPattern;
 
-    private String validatorClass;
+    private String validator;
 
     private String enumerationValues;
 
@@ -105,12 +105,12 @@ public class PlainSchemaTO extends AbstractSchemaTO {
         this.type = type;
     }
 
-    public String getValidatorClass() {
-        return validatorClass;
+    public String getValidator() {
+        return validator;
     }
 
-    public void setValidatorClass(final String validatorClass) {
-        this.validatorClass = validatorClass;
+    public void setValidator(final String validator) {
+        this.validator = validator;
     }
 
     public String getEnumerationValues() {
index 5dca6f5..fadaa15 100644 (file)
@@ -23,9 +23,12 @@ import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.core.persistence.api.dao.DuplicateException;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -63,6 +66,17 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
 
     @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_CREATE + "')")
     public ImplementationTO create(final ImplementationTO implementationTO) {
+        if (StringUtils.isBlank(implementationTO.getKey())) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
+            sce.getElements().add("Implementation key");
+            throw sce;
+        }
+
+        Implementation implementation = implementationDAO.find(implementationTO.getKey());
+        if (implementation != null) {
+            throw new DuplicateException(implementationTO.getKey());
+        }
+
         return binder.getImplementationTO(implementationDAO.save(binder.create(implementationTO)));
     }
 
index 9327266..4f7cbd9 100644 (file)
@@ -26,7 +26,8 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
  */
 public interface AccountRule {
 
-    void setConf(AccountRuleConf conf);
+    default void setConf(AccountRuleConf conf) {
+    }
 
     void enforce(User user);
 }
index 8ac914a..3b23d6e 100644 (file)
@@ -26,9 +26,12 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
  */
 public interface PasswordRule {
 
-    PasswordRuleConf getConf();
+    default PasswordRuleConf getConf() {
+        return null;
+    }
 
-    void setConf(PasswordRuleConf conf);
+    default void setConf(PasswordRuleConf conf) {
+    }
 
     void enforce(User user);
 }
index 5366403..ab05f4a 100644 (file)
@@ -34,7 +34,8 @@ public interface Reportlet {
      *
      * @param conf configuration
      */
-    void setConf(ReportletConf conf);
+    default void setConf(ReportletConf conf) {
+    }
 
     /**
      * Actual data extraction for reporting.
index cde22ef..72a7a44 100644 (file)
@@ -196,9 +196,9 @@ under the License.
   <AccountPolicyRule policy_id="06e2ed52-6966-44aa-a177-a0ca7434201f" implementation_id="DefaultAccountRuleConf2"/>
   <PullPolicy id="4ad10d94-e002-4b3f-b771-16089cc71da9" description="pull policy 1" specification='{"conflictResolutionAction":"IGNORE"}'/>
   <PasswordPolicy id="55e5de0b-c79c-4e66-adda-251b6fb8579a" description="sample password policy" historyLength="0" allowNullPassword="0"/> 
-  <Implementation id="DefaultAccountRuleConf3" type="PASSWORD_RULE" engine="JAVA"
+  <Implementation id="DefaultPasswordRuleConf3" type="PASSWORD_RULE" engine="JAVA"
                   body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
-  <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultAccountRuleConf3"/>
+  <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
   <PullPolicy id="9454b0d7-2610-400a-be82-fc23cf553dd6" description="pull policy for java rule"
               specification='{"conflictResolutionAction":"IGNORE"}'/>
 
index 2b98076..65aa6f6 100644 (file)
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.provisioning.java.data;
 
 import java.lang.reflect.Modifier;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.RuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
@@ -66,15 +67,20 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
 
     @Override
     public void update(final Implementation implementation, final ImplementationTO implementationTO) {
-        BeanUtils.copyProperties(implementationTO, implementation);
-
         SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidImplementation);
 
-        if (implementation.getBody() == null) {
+        if (implementation.getType() != null && implementation.getType() != implementationTO.getType()) {
+            sce.getElements().add("ImplementationType cannot be changed");
+            throw sce;
+        }
+
+        if (StringUtils.isBlank(implementationTO.getBody())) {
             sce.getElements().add("No actual implementation provided");
             throw sce;
         }
 
+        BeanUtils.copyProperties(implementationTO, implementation);
+
         if (implementation.getEngine() == ImplementationEngine.JAVA) {
             Class<?> base = null;
             switch (implementation.getType()) {
index dfa3a8e..0632e2c 100644 (file)
@@ -37,12 +37,14 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.slf4j.Logger;
@@ -55,7 +57,7 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
 
     private static final Logger LOG = LoggerFactory.getLogger(SchemaDataBinder.class);
 
-    private static final String[] IGNORE_PROPERTIES = { "anyTypeClass", "provision", "resource" };
+    private static final String[] IGNORE_PROPERTIES = { "anyTypeClass", "provision", "resource", "validator" };
 
     @Autowired
     private AnyTypeClassDAO anyTypeClassDAO;
@@ -76,6 +78,9 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
     private AnyTypeDAO anyTypeDAO;
 
     @Autowired
+    private ImplementationDAO implementationDAO;
+
+    @Autowired
     private EntityFactory entityFactory;
 
     @Autowired
@@ -91,6 +96,18 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
 
         BeanUtils.copyProperties(schemaTO, schema, IGNORE_PROPERTIES);
 
+        if (schemaTO.getValidator() == null) {
+            schema.setValidator(null);
+        } else {
+            Implementation validator = implementationDAO.find(schemaTO.getValidator());
+            if (validator == null) {
+                LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
+                        schemaTO.getValidator());
+            } else {
+                schema.setValidator(validator);
+            }
+        }
+
         PlainSchema merged = plainSchemaDAO.save(schema);
 
         if (schemaTO.getAnyTypeClass() != null
@@ -155,6 +172,9 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
         PlainSchemaTO schemaTO = new PlainSchemaTO();
         BeanUtils.copyProperties(schema, schemaTO, IGNORE_PROPERTIES);
         schemaTO.setAnyTypeClass(schema.getAnyTypeClass() == null ? null : schema.getAnyTypeClass().getKey());
+        if (schema.getValidator() != null) {
+            schemaTO.setValidator(schema.getValidator().getKey());
+        }
 
         return schemaTO;
     }
index dd2fb52..f46a5f8 100644 (file)
@@ -144,7 +144,6 @@ public class SAML2IdPsDirectoryPanel extends DirectoryPanel<
 
             @Override
             public void onClose(final AjaxRequestTarget target) {
-//                target.add(content);
                 templateModal.show(false);
             }
         });
@@ -164,7 +163,6 @@ public class SAML2IdPsDirectoryPanel extends DirectoryPanel<
                 importMetadata.toggle(target, true);
             }
         };
-
         ((WebMarkupContainer) get("container:content")).addOrReplace(importMetadataLink);
     }
 
@@ -193,7 +191,7 @@ public class SAML2IdPsDirectoryPanel extends DirectoryPanel<
         columns.add(new BooleanPropertyColumn<>(
                 new ResourceModel("useDeflateEncoding"), "useDeflateEncoding", "useDeflateEncoding"));
         columns.add(new BooleanPropertyColumn<>(
-            new ResourceModel("supportUnsolicited"), "supportUnsolicited", "supportUnsolicited"));
+                new ResourceModel("supportUnsolicited"), "supportUnsolicited", "supportUnsolicited"));
         columns.add(new PropertyColumn<>(
                 new ResourceModel("bindingType"), "bindingType", "bindingType"));
         columns.add(new BooleanPropertyColumn<>(