class CustomDataSourceDefinitionToClientConverter implements ToClientConverter<CustomDataSourceDefinition, ClientCustomDataSourceDefinition, ToClientConversionOptions> {

    @Override
    public ClientCustomDataSourceDefinition toClient(CustomDataSourceDefinition serverObject, ToClientConversionOptions options) {
        final ClientCustomDataSourceDefinition clientDefinition = new ClientCustomDataSourceDefinition().setName(serverObject.getName());
        if (serverObject.getPropertyDefinitions() != null) {
            final List<CustomDataSourcePropertyDefinition> propertyDefinitions = new ArrayList<CustomDataSourcePropertyDefinition>();
            for (Map<String, ?> currentDefinition : serverObject.getPropertyDefinitions()) {
                final Object hidden = currentDefinition.get(CustomDataSourceDefinition.PARAM_HIDDEN);
                if (hidden == null || (hidden instanceof String && !Boolean.valueOf((String) hidden))) {
                    final CustomDataSourcePropertyDefinition currentPropertyDefinition = new CustomDataSourcePropertyDefinition()
                            .setName((String) currentDefinition.get(CustomDataSourceDefinition.PARAM_NAME))
                            .setDefaultValue((String) currentDefinition.get(CustomDataSourceDefinition.PARAM_DEFAULT))
                            .setLabel((String) currentDefinition.get(CustomDataSourceDefinition.PARAM_LABEL));
                    final ArrayList<ClientProperty> properties = new ArrayList<ClientProperty>();
                    for (String currentParameter : currentDefinition.keySet()) {
                        if (!(CustomDataSourceDefinition.PARAM_NAME.equals(currentParameter)
                                || CustomDataSourceDefinition.PARAM_DEFAULT.equals(currentParameter)
                                || CustomDataSourceDefinition.PARAM_LABEL.equals(currentParameter))) {
                            properties.add(new ClientProperty(currentParameter, (String) currentDefinition.get(currentParameter)));
                        }
                    }
                    if (!properties.isEmpty()) currentPropertyDefinition.setProperties(properties);
                    propertyDefinitions.add(currentPropertyDefinition);
                }
            }
            if (!propertyDefinitions.isEmpty()) clientDefinition.setPropertyDefinitions(propertyDefinitions);
        }
        if (serverObject.getQueryExecuterMap() != null && !serverObject.getQueryExecuterMap().isEmpty()) {
            clientDefinition.setQueryTypes(new ArrayList<String>(serverObject.getQueryExecuterMap().keySet()));
        }
        try {
            Class<?> serviceClass = Class.forName(serverObject.getServiceClassName());
            // Instance created to evaluate if it implements the test interface
            Object newServiceClass = serviceClass.newInstance();
            clientDefinition.setTestable(newServiceClass instanceof CustomReportDataSourceService);
        } catch (Exception e) {
            // can't get service class instance here. Then it's not testable
        }
        return clientDefinition;
    }

}