Package org.cyclop.web.panels.queryimport

Source Code of org.cyclop.web.panels.queryimport.QueryImportPanel

/*
* 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.cyclop.web.panels.queryimport;

import java.io.ByteArrayInputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.markup.html.form.upload.FileUploadField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.protocol.http.WebSession;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.util.lang.Bytes;
import org.cyclop.common.AppConfig;
import org.cyclop.model.UserPreferences;
import org.cyclop.service.importer.QueryImporter;
import org.cyclop.service.importer.model.ImportConfig;
import org.cyclop.service.importer.model.ImportStats;
import org.cyclop.service.um.UserManager;
import org.cyclop.web.common.ImmutableListModel;
import org.cyclop.web.common.JsFunctionBuilder;
import org.cyclop.web.components.pagination.BootstrapPagingNavigator;
import org.cyclop.web.components.pagination.PagerConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** @author Maciej Miklas */
public class QueryImportPanel extends Panel {

  private final static Logger LOG = LoggerFactory.getLogger(QueryImportPanel.class);

  private static final JavaScriptResourceReference JS_IMPORT = new JavaScriptResourceReference(
      QueryImportPanel.class, "queryImport.js");

  private ImmutableListModel<ImportResult> resultModel;

  private AppConfig conf = AppConfig.get();

  private WebMarkupContainer importResultContainer;

  @Inject
  @Named(QueryImporter.IMPL_SERIAL)
  private QueryImporter serialImporter;

  @Inject
  @Named(QueryImporter.IMPL_PARALLEL)
  private QueryImporter parallelImporter;

  @Inject
  private UserManager um;

  private ThreadLocal<DecimalFormat> NUMBER_FORMAT = new ThreadLocal<DecimalFormat>() {
    protected DecimalFormat initialValue() {
      DecimalFormat nf = (DecimalFormat) NumberFormat.getNumberInstance(WebSession.get().getLocale());
      nf.applyPattern("###.###");
      return nf;
    };
  };

  public QueryImportPanel(String id) {
    super(id);
  }

  @Override
  protected void onInitialize() {
    super.onInitialize();

    ImportOptions importOptions = createImportOptions();
    setDefaultModel(new CompoundPropertyModel<>(importOptions));

    Form<?> form = initFileUpload(importOptions);
    initUploadOptions(form);

    importResultContainer = initImportResultContainer();
    resultModel = initResultTable(importResultContainer);
  }

  private ImportOptions createImportOptions() {
    ImportOptions importOptions = new ImportOptions();
    UserPreferences prefs = um.readPreferences();
    importOptions.setContinueWithErrors(prefs.isImportContinueWithErrors());
    importOptions.setIncludeInHistory(prefs.isImportIncludeInHistory());
    importOptions.setParallel(prefs.isImportParallel());
    return importOptions;
  }

  private String createStatsMessage(ImportStats stats) {
    StringBuilder buf = new StringBuilder();
    DecimalFormat nf = NUMBER_FORMAT.get();
    buf.append("Executed ").append(nf.format(stats.errorCount + stats.successCount)).append(" queries in ")
        .append(stats.runtime.toString()).append(", ").append(nf.format(stats.successCount))
        .append(" were succesfull, ").append(nf.format(stats.errorCount)).append(" failed");
    String resp = buf.toString();
    LOG.info(resp);
    return resp;
  }

  private void executeImport(AjaxRequestTarget target, ImportOptions importOptions, FileUpload upload) {
    byte[] fileContentBytes = upload.getBytes();
    LOG.debug("Importing file of {} bytes", fileContentBytes.length);

    ImportResultWriter result = new ImportResultWriter();

    ImportConfig config = createImportConfig(importOptions);
    ImportStats stats = getImporter(importOptions).importScript(new ByteArrayInputStream(fileContentBytes), result,
        config);

    resultModel.setObject(result.getResult());

    String resp = createStatsMessage(stats);
    sendJsResponse(target, resp);
    importResultContainer.setVisible(true);
    target.add(importResultContainer);

    updatePreferences(importOptions);
  }

  private ImportConfig createImportConfig(ImportOptions importOptions) {
    ImportConfig config = new ImportConfig();
    config.withContinueWithErrors(importOptions.isContinueWithErrors()).withUpdateHistory(
        importOptions.isContinueWithErrors());
    return config;
  }

  private QueryImporter getImporter(ImportOptions importOptions) {
    return importOptions.isParallel() ? parallelImporter : serialImporter;

  }

  private Form<?> initFileUpload(final ImportOptions importOptions) {
    final FileUploadField scriptFile = new FileUploadField("scriptFile");

    final Form<?> form = new Form<Void>("form") {
      @Override
      protected void onSubmit() {
      }
    };
    form.setMaxSize(Bytes.megabytes(conf.queryImport.maxFileSizeMb));
    add(form);
    form.add(scriptFile);

    form.add(new AjaxButton("ajaxSubmit") {
      @Override
      protected void onError(AjaxRequestTarget target, Form<?> form) {
        LOG.info("Got error on import upload: {}", form);
        sendJsResponse(target, ErrorCodes.FILE_SIZE_LIMIT.name());
      }

      @Override
      protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
        FileUpload upload = scriptFile.getFileUpload();
        if (upload == null) {
          return;
        }
        executeImport(target, importOptions, upload);
      }
    });
    return form;
  }

  private WebMarkupContainer initImportResultContainer() {
    WebMarkupContainer historyContainer = new WebMarkupContainer("importResultContainer");
    historyContainer.setOutputMarkupPlaceholderTag(true);
    historyContainer.setVisible(false);
    add(historyContainer);
    return historyContainer;
  }

  private ImmutableListModel<ImportResult> initResultTable(final WebMarkupContainer container) {
    ImmutableListModel<ImportResult> model = new ImmutableListModel<>();

    PageableListView<ImportResult> historyTable = new PageableListView<ImportResult>("resultRow", model, 1) {

      @Override
      protected void populateItem(ListItem<ImportResult> item) {
        ImportResult entry = item.getModel().getObject();
        if (entry == null) {
          return;
        }
        populateRuntime(item, entry);
        populateQuery(item, entry);
      }
    };
    container.add(historyTable);
    final BootstrapPagingNavigator importResultPager = new BootstrapPagingNavigator("importResultPager",
        historyTable, new PagerConfigurator() {

          @Override
          public void onItemsPerPageChanged(AjaxRequestTarget target, long newItemsPerPage) {
            UserPreferences prefs = um.readPreferences().setPagerImportItems(newItemsPerPage);
            um.storePreferences(prefs);
          }

          @Override
          public long getInitialItemsPerPage() {
            return um.readPreferences().getPagerImportItems();
          }
        });
    container.add(importResultPager);
    model.registerOnChangeListener(o -> importResultPager.reset());
    return model;
  }

  private void initUploadOptions(Form<?> form) {
    CheckBox continueWithErrors = new CheckBox("continueWithErrors");
    form.add(continueWithErrors);

    CheckBox includeInHistory = new CheckBox("includeInHistory");
    form.add(includeInHistory);

    CheckBox parallel = new CheckBox("parallel");
    form.add(parallel);
  }

  private void populateQuery(ListItem<ImportResult> item, ImportResult entry) {
    Label queryLabel = new Label("query", entry.query.toDisplayString());
    queryLabel.setEscapeModelStrings(false);
    item.add(queryLabel);

    WebMarkupContainer errorContainer = new WebMarkupContainer("queryError");
    item.add(errorContainer);
    if (entry.error == null) {
      errorContainer.setVisible(false);
    } else {
      Label errorLabel = new Label("error", entry.error);
      errorContainer.add(errorLabel);
    }
  }

  private void populateRuntime(ListItem<ImportResult> item, ImportResult result) {
    String dateStr = Long.toString(result.runTime);
    Label executedOn = new Label("runtime", dateStr);
    item.add(executedOn);
  }

  @Override
  public void renderHead(IHeaderResponse response) {
    super.renderHead(response);
    response.render(JavaScriptReferenceHeaderItem.forReference(JS_IMPORT));
  }

  private void sendJsResponse(AjaxRequestTarget target, String response) {
    String js = JsFunctionBuilder.function("onQueryImportResponse").param(response).build();
    target.appendJavaScript(js);
  }

  private void updatePreferences(ImportOptions importOptions) {
    UserPreferences prefs = um.readPreferences();
    prefs.setImportContinueWithErrors(importOptions.isContinueWithErrors())
        .setImportIncludeInHistory(importOptions.isIncludeInHistory())
        .setImportParallel(importOptions.isParallel());
    um.storePreferences(prefs);
  }

}
TOP

Related Classes of org.cyclop.web.panels.queryimport.QueryImportPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.