org.jboss.hal.client.configuration.subsystem.datasource.wizard.PropertiesStep.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.hal.client.configuration.subsystem.datasource.wizard.PropertiesStep.java

Source

/*
 * Copyright 2015-2016 Red Hat, Inc, and individual contributors.
 *
 * Licensed 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
 *
 * https://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.jboss.hal.client.configuration.subsystem.datasource.wizard;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import javax.inject.Provider;

import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import elemental2.dom.HTMLElement;
import org.jboss.hal.ballroom.autocomplete.StaticAutoComplete;
import org.jboss.hal.ballroom.form.Form;
import org.jboss.hal.ballroom.form.PropertiesItem;
import org.jboss.hal.ballroom.wizard.WizardStep;
import org.jboss.hal.config.Environment;
import org.jboss.hal.core.mbui.form.ModelNodeForm;
import org.jboss.hal.core.runtime.TopologyTasks;
import org.jboss.hal.core.runtime.server.Server;
import org.jboss.hal.dmr.ModelNode;
import org.jboss.hal.dmr.Operation;
import org.jboss.hal.dmr.Property;
import org.jboss.hal.dmr.ResourceAddress;
import org.jboss.hal.dmr.dispatch.Dispatcher;
import org.jboss.hal.flow.FlowContext;
import org.jboss.hal.flow.FlowException;
import org.jboss.hal.flow.Outcome;
import org.jboss.hal.flow.Progress;
import org.jboss.hal.flow.Task;
import org.jboss.hal.meta.Metadata;
import org.jboss.hal.meta.StatementContext;
import org.jboss.hal.resources.Ids;
import org.jboss.hal.resources.Resources;
import org.jetbrains.annotations.NonNls;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Completable;

import static org.jboss.hal.dmr.ModelDescriptionConstants.*;
import static org.jboss.hal.dmr.ModelNodeHelper.failSafeGet;
import static org.jboss.hal.flow.Flow.series;

class PropertiesStep extends WizardStep<Context, State> {

    @NonNls
    private static final Logger logger = LoggerFactory.getLogger(DataSourceWizard.class);

    private final ModelNode dummy;
    private final Form<ModelNode> form;
    private final PropertiesItem propertiesItem;
    private Dispatcher dispatcher;
    private StatementContext statementContext;
    private Environment environment;
    private Provider<Progress> progress;
    private Resources resources;
    private StaticAutoComplete propsAutoComplete;

    PropertiesStep(Dispatcher dispatcher, StatementContext statementContext, Environment environment,
            Provider<Progress> progress, Metadata metadata, Resources resources) {
        super(resources.constants().xaProperties());
        this.dispatcher = dispatcher;
        this.statementContext = statementContext;
        this.environment = environment;
        this.progress = progress;
        this.resources = resources;

        dummy = new ModelNode().setEmptyObject();
        propertiesItem = new PropertiesItem(VALUE);
        propertiesItem.setRequired(true);
        ModelNode propertiesDescription = failSafeGet(metadata.getDescription(), "attributes/value/description"); //NON-NLS
        form = new ModelNodeForm.Builder<>(Ids.DATA_SOURCE_PROPERTIES_FORM, Metadata.empty())
                .unboundFormItem(propertiesItem, 0, SafeHtmlUtils.fromString(propertiesDescription.asString()))
                .build();
        propsAutoComplete = new StaticAutoComplete(Collections.emptyList());
        propertiesItem.registerSuggestHandler(propsAutoComplete);
        registerAttachable(form);
    }

    @Override
    public HTMLElement element() {
        return form.element();
    }

    @Override
    protected void onShow(Context context) {
        propertiesItem.setValue(context.xaProperties);
        propertiesItem.setUndefined(false);
        propertiesItem.setEnabled(!context.isCreated()); // can only be changed if DS was not already created
        String dsClassname = context.dataSource.hasDefined(XA_DATASOURCE_CLASS)
                ? context.dataSource.get(XA_DATASOURCE_CLASS).asString()
                : null;
        readJdbcDriverProperties(true, dsClassname, context.dataSource.get(DRIVER_NAME).asString(),
                propsAutoComplete::update);
        form.edit(dummy);
    }

    private void readJdbcDriverProperties(boolean isXa, String dsClassname, String driverName,
            Consumer<List<String>> callback) {
        List<Task<FlowContext>> tasks = new ArrayList<>();

        // check running server(s)
        if (!environment.isStandalone()) {
            tasks.add(
                    new TopologyTasks.RunningServersQuery(environment, dispatcher, environment.isStandalone() ? null
                            : new ModelNode().set(PROFILE_NAME, statementContext.selectedProfile())));
        }

        // read jdbc-driver datasource properties
        tasks.add(flowContext -> {
            ResourceAddress address;
            if (environment.isStandalone()) {
                address = Server.STANDALONE.getServerAddress();
            } else {
                List<Server> servers = flowContext.get(TopologyTasks.RUNNING_SERVERS);
                if (!servers.isEmpty()) {
                    Server server = servers.get(0);
                    address = server.getServerAddress();
                } else {
                    String message = resources.messages()
                            .readDatasourcePropertiesErrorDomain(statementContext.selectedProfile());
                    return Completable.error(new FlowException(message, flowContext));
                }
            }
            address.add(SUBSYSTEM, DATASOURCES).add(JDBC_DRIVER, driverName);
            Operation operation = new Operation.Builder(address, READ_RESOURCE_OPERATION)
                    .param(INCLUDE_RUNTIME, true).build();
            return dispatcher.execute(operation).doOnSuccess(result -> flowContext.set(RESULT, result))
                    .toCompletable();
        });

        series(new FlowContext(progress.get()), tasks).subscribe(new Outcome<FlowContext>() {
            @Override
            public void onError(FlowContext flowContext, Throwable error) {
                logger.warn("Failed to read jdbc-driver. Cause: {}", error.getMessage());
            }

            @Override
            public void onSuccess(FlowContext flowContext) {
                ModelNode result = flowContext.get(RESULT);
                List<String> properties = Collections.emptyList();
                String datasourceClassname;
                if (dsClassname == null) {
                    String attribute = isXa ? DRIVER_XA_DATASOURCE_CLASS_NAME : DRIVER_DATASOURCE_CLASS_NAME;
                    datasourceClassname = result.get(attribute).asString();
                } else {
                    datasourceClassname = dsClassname;
                }
                if (result.hasDefined(DATASOURCE_CLASS_INFO)) {
                    properties = result.get(DATASOURCE_CLASS_INFO).asList().stream()
                            .filter(node -> datasourceClassname.equals(node.asProperty().getName()))
                            .flatMap(node -> node.asProperty().getValue().asPropertyList().stream())
                            .map(Property::getName).collect(Collectors.toList());
                }
                callback.accept(properties);
            }
        });
    }

    @Override
    protected boolean onNext(Context context) {
        boolean valid = form.save();
        if (valid) {
            context.xaProperties.clear();
            context.xaProperties.putAll(propertiesItem.getValue());
        }
        return valid;
    }

    @Override
    protected boolean onBack(Context context) {
        form.cancel();
        return true;
    }

    @Override
    protected boolean onCancel(Context context) {
        form.cancel();
        return true;
    }
}