All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.anwiba.spatial.swing.ckan.search.DatasetTableFactory Maven / Gradle / Ivy

There is a newer version: 1.2.50
Show newest version
/*
 * #%L
 * *
 * %%
 * Copyright (C) 2007 - 2018 Andreas W. Bartels ([email protected])
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package net.anwiba.spatial.swing.ckan.search;

import java.awt.Desktop;
import java.awt.Window;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import net.anwiba.commons.datasource.connection.IHttpConnectionDescription;
import net.anwiba.commons.lang.collection.IObjectIterable;
import net.anwiba.commons.lang.object.ObjectPair;
import net.anwiba.commons.lang.stream.Streams;
import net.anwiba.commons.logging.ILevel;
import net.anwiba.commons.message.MessageBuilder;
import net.anwiba.commons.model.BooleanModel;
import net.anwiba.commons.model.IBooleanDistributor;
import net.anwiba.commons.model.IChangeableListListener;
import net.anwiba.commons.model.IObjectModel;
import net.anwiba.commons.model.ISelectionModel;
import net.anwiba.commons.model.IntegerModel;
import net.anwiba.commons.preferences.IPreferences;
import net.anwiba.commons.swing.action.ConfigurableActionBuilder;
import net.anwiba.commons.swing.combobox.ObjectComboBoxModel;
import net.anwiba.commons.swing.dialog.ConfigurableDialogLauncher;
import net.anwiba.commons.swing.dialog.DataState;
import net.anwiba.commons.swing.dialog.DialogResult;
import net.anwiba.commons.swing.dialog.IContentPaneFactory;
import net.anwiba.commons.swing.dialog.IDialogResult;
import net.anwiba.commons.swing.dialog.pane.AbstractContentPane;
import net.anwiba.commons.swing.dialog.pane.IContentPanel;
import net.anwiba.commons.swing.table.IColumnValueProvider;
import net.anwiba.commons.swing.table.IKeyListenerFactory;
import net.anwiba.commons.swing.table.IMouseListenerFactory;
import net.anwiba.commons.swing.table.IObjectListColumnConfiguration;
import net.anwiba.commons.swing.table.IObjectTableModel;
import net.anwiba.commons.swing.table.ISelectionIndexModel;
import net.anwiba.commons.swing.table.ObjectListColumnConfiguration;
import net.anwiba.commons.swing.table.ObjectListTable;
import net.anwiba.commons.swing.table.ObjectTableBuilder;
import net.anwiba.commons.swing.table.renderer.BooleanRenderer;
import net.anwiba.commons.swing.table.renderer.ObjectUiTableCellRenderer;
import net.anwiba.commons.swing.ui.IObjectUi;
import net.anwiba.commons.swing.ui.ObjectUiBuilder;
import net.anwiba.commons.swing.ui.ObjectUiListCellRenderer;
import net.anwiba.commons.utilities.collection.IterableUtilities;
import net.anwiba.commons.utilities.string.StringUtilities;
import net.anwiba.spatial.ckan.json.schema.v1_0.Dataset;
import net.anwiba.spatial.ckan.request.sort.ISortOrder;
import net.anwiba.spatial.ckan.request.sort.ISortOrderTerm;
import net.anwiba.spatial.ckan.request.sort.ISortOrderVisitor;
import net.anwiba.spatial.ckan.request.sort.Order;
import net.anwiba.spatial.ckan.request.sort.SortOrderList;
import net.anwiba.spatial.ckan.request.sort.SortOrderTerm;
import net.anwiba.spatial.ckan.utilities.CkanUtilities;
import net.anwiba.spatial.swing.ckan.search.message.Messages;

public class DatasetTableFactory {

  private static net.anwiba.commons.logging.ILogger logger = net.anwiba.commons.logging.Logging
      .getLogger(DatasetTableFactory.class);
  private final int numberOfResultRows;

  public DatasetTableFactory(final int numberOfResultRows) {
    this.numberOfResultRows = numberOfResultRows;
  }

  ObjectListTable create(
      final IHttpConnectionDescription description,
      final IntegerModel offsetModel,
      final IntegerModel resultCountModel,
      final IntegerModel selectedIndexModel,
      final IObjectModel sortOrderModel,
      final List datasets) {
    return new ObjectTableBuilder()
        .setSingleSelectionMode()
        .setValues(datasets)
        .setHeaderMouseListenerFactory(new IMouseListenerFactory() {

          @Override
          public MouseListener create(
              final IObjectTableModel tableModel,
              final ISelectionIndexModel selectionIndexModel,
              final ISelectionModel selectionModel,
              final IBooleanDistributor sortStateModel) {
            return new MouseAdapter() {

              @Override
              public void mouseClicked(final MouseEvent e) {
                final List> sortOrderTerms = getSortOrderTerms(sortOrderModel);
                final ObjectListTable> table = new ObjectTableBuilder>()
                    .setValues(sortOrderTerms)
                    .setPreferredVisibleRowCount(3)
                    .addColumn(createEnabledColumn())
                    .addColumn(createAspectColumn())
                    .addColumn(createOrderTypeColumn())
                    .addMoveObjectDownAction()
                    .addMoveObjectUpAction()
                    .build();
                final IDialogResult result = new ConfigurableDialogLauncher()
                    .setCancleOkButtonDialog()
                    .enableCloseOnEscape()
                    .setTitle("Datasets")
                    .setMessage(
                        new MessageBuilder().setText("Sort order").setDescription("Please, set sort order").build())
                    .setContentPaneFactory(new IContentPaneFactory() {

                      @Override
                      public IContentPanel create(final Window owner, final IPreferences preferences) {
                        return new AbstractContentPane() {

                          @Override
                          public JComponent getComponent() {
                            table.getTableModel().addTableModelListener(new TableModelListener() {

                              @Override
                              public void tableChanged(final TableModelEvent e) {
                                getDataStateModel().set(DataState.MODIFIED);
                              }
                            });
                            table.getTableModel().addListModelListener(
                                new IChangeableListListener>() {
                                  @Override
                                  public void objectsChanged(
                                      final Iterable> oldObjects,
                                      final Iterable> newObjects) {
                                    getDataStateModel().set(DataState.MODIFIED);
                                  }
                                });
                            return table.getComponent();
                          }
                        };
                      }
                    })
                    .launch(e.getComponent());
                if (!DialogResult.OK.equals(result)) {
                  return;
                }
                sortOrderModel.set(create(table.getTableModel().values()));
              }

              private IObjectListColumnConfiguration> createOrderTypeColumn() {
                final ObjectComboBoxModel comboBoxComponentModel = new ObjectComboBoxModel<>(
                    Arrays.asList(Order.values()));
                final JComboBox comboBox = new JComboBox<>(comboBoxComponentModel);
                final IObjectUi objectUi = new ObjectUiBuilder().icon(o -> {
                  switch (o) {
                    case asc: {
                      return net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.PAN_UP
                          .getSmallIcon();
                    }
                    case desc: {
                      return net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.PAN_DOWN
                          .getSmallIcon();
                    }
                  }
                  return net.anwiba.commons.swing.icons.GuiIcons.EMPTY_ICON.getSmallIcon();
                }).text(o -> null).build();
                comboBox.setRenderer(new ObjectUiListCellRenderer<>(objectUi));
                final DefaultCellEditor cellEditor = new DefaultCellEditor(comboBox);
                cellEditor.setClickCountToStart(2);
                return new ObjectListColumnConfiguration<>(
                    "Order",
                    (IColumnValueProvider>) object -> {
                      if (object == null) {
                        return null;
                      }
                      return object.getSecondObject().getOrder();
                    },
                    new ObjectUiTableCellRenderer<>(objectUi, Order.class, SwingConstants.CENTER),
                    (object, value) -> {
                      if (object == null) {
                        return object;
                      }
                      return new ObjectPair<>(
                          object.getFirstObject(),
                          new SortOrderTerm((Order) value, object.getSecondObject().getAspect()));
                    },
                    cellEditor,
                    30,
                    false,
                    null);
              }

              private IObjectListColumnConfiguration> createAspectColumn() {
                final IObjectUi objectUi = new ObjectUiBuilder().text(o -> {
                  if ("metadata_created".equals(o)) {
                    return "created";
                  }
                  if ("metadata_modified".equals(o)) {
                    return "modified";
                  }
                  return o;
                }).build();
                return new ObjectListColumnConfiguration<>(
                    "Aspect",
                    (IColumnValueProvider>) object -> {
                      if (object == null) {
                        return null;
                      }
                      return object.getSecondObject().getAspect();
                    },
                    new ObjectUiTableCellRenderer<>(objectUi, String.class, SwingConstants.LEFT),
                    100,
                    String.class,
                    false,
                    null);
              }

              private IObjectListColumnConfiguration> createEnabledColumn() {
                final JCheckBox checkBox = new JCheckBox();
                checkBox.setHorizontalAlignment(SwingConstants.CENTER);
                final DefaultCellEditor cellEditor = new DefaultCellEditor(checkBox);
                return new ObjectListColumnConfiguration<>(
                    "Enabled",
                    (IColumnValueProvider>) object -> {
                      if (object == null) {
                        return null;
                      }
                      return object.getFirstObject();
                    },
                    new BooleanRenderer(),
                    (object, value) -> {
                      if (object == null) {
                        return object;
                      }
                      return new ObjectPair<>(
                          (Boolean) value,
                          new SortOrderTerm(object.getSecondObject().getOrder(), object.getSecondObject().getAspect()));
                    },
                    cellEditor,
                    30,
                    false,
                    null);
              }

              private ISortOrder create(final IObjectIterable> values) {
                final Collection collection = Streams
                    .of(values)
                    .filter(v -> v.getFirstObject())
                    .convert(v -> v.getSecondObject())
                    .asCollection();
                if (collection.size() == 1) {
                  return collection.iterator().next();
                }
                return new SortOrderList(collection);
              }

              private List> getSortOrderTerms(
                  @SuppressWarnings("hiding") final IObjectModel sortOrderModel) {
                final ISortOrderVisitor, RuntimeException> visitor = new ISortOrderVisitor, RuntimeException>() {

                  @Override
                  public List visitList(final Iterable terms) {
                    return IterableUtilities.asList(terms);
                  }

                  @Override
                  public List visitTerm(final ISortOrderTerm term) {
                    return Arrays.asList(term);
                  }
                };
                final List terms = sortOrderModel.get().accept(visitor);
                ISortOrderTerm relevanceSortOrderTerm = null;
                ISortOrderTerm metadataCreatedSortOrderTerm = null;
                ISortOrderTerm metadataModifiedSortOrderTerm = null;
                final List> enabledStateTermList = new ArrayList<>();
                for (final ISortOrderTerm term : terms) {
                  if ("relevance".equals(term.getAspect())) {
                    relevanceSortOrderTerm = term;
                    enabledStateTermList.add(new ObjectPair<>(Boolean.TRUE, term));
                  }
                  if ("metadata_created".equals(term.getAspect())) {
                    metadataCreatedSortOrderTerm = term;
                    enabledStateTermList.add(new ObjectPair<>(Boolean.TRUE, term));
                  }
                  if ("metadata_modified".equals(term.getAspect())) {
                    metadataModifiedSortOrderTerm = term;
                    enabledStateTermList.add(new ObjectPair<>(Boolean.TRUE, term));
                  }
                }
                if (relevanceSortOrderTerm == null) {
                  enabledStateTermList.add(
                      new ObjectPair(
                          Boolean.FALSE,
                          new SortOrderTerm(Order.asc, "relevance")));
                }
                if (metadataCreatedSortOrderTerm == null) {
                  enabledStateTermList.add(
                      new ObjectPair(
                          Boolean.FALSE,
                          new SortOrderTerm(Order.desc, "metadata_created")));
                }
                if (metadataModifiedSortOrderTerm == null) {
                  enabledStateTermList.add(
                      new ObjectPair(
                          Boolean.FALSE,
                          new SortOrderTerm(Order.desc, "metadata_modified")));
                }
                return enabledStateTermList;
              }
            };
          }
        })
        .addStringColumn(Messages.title, value -> value == null ? null : CkanUtilities.toString(value), 40)
        .addActionFactory((tableModel, selectionIndexModel, selectionModel, sortStateModel) -> {
          final BooleanModel enabledModel = new BooleanModel(false);
          tableModel.addTableModelListener(e -> enabledModel.set(offsetModel.getValue() > 0));
          return new ConfigurableActionBuilder()
              .setIcon(net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.GO_FIRST)
              .setEnabledDistributor(enabledModel)
              .setProcedure(component -> {
                if (selectionIndexModel.isEmpty()) {
                  selectedIndexModel.setValue(-1);
                } else {
                  selectedIndexModel.setValue(selectionIndexModel.getMinimum());
                }
                offsetModel.setValue(0);
              })
              .build();
        })
        .addActionFactory((tableModel, selectionIndexModel, selectionModel, sortStateModel) -> {
          final BooleanModel enabledModel = new BooleanModel(false);
          tableModel.addTableModelListener(e -> enabledModel.set(offsetModel.getValue() > 0));
          return new ConfigurableActionBuilder()
              .setIcon(net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.GO_PREVIOUS)
              .setEnabledDistributor(enabledModel)
              .setProcedure(component -> {
                if (selectionIndexModel.isEmpty()) {
                  selectedIndexModel.setValue(-1);
                } else {
                  selectedIndexModel.setValue(selectionIndexModel.getMinimum());
                }
                offsetModel.setValue(
                    offsetModel.getValue() > this.numberOfResultRows
                        ? offsetModel.getValue() - this.numberOfResultRows
                        : 0);
              })
              .build();
        })
        .addActionFactory((tableModel, selectionIndexModel, selectionModel, sortStateModel) -> {
          final BooleanModel enabledModel = new BooleanModel(
              offsetModel.getValue() + tableModel.size() < resultCountModel.getValue());
          tableModel.addTableModelListener(
              e -> enabledModel.set(offsetModel.getValue() + tableModel.size() < resultCountModel.getValue()));
          return new ConfigurableActionBuilder()
              .setIcon(net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.GO_NEXT)
              .setEnabledDistributor(enabledModel)
              .setProcedure(component -> {
                if (selectionIndexModel.isEmpty()) {
                  selectedIndexModel.setValue(-1);
                } else {
                  selectedIndexModel.setValue(selectionIndexModel.getMinimum());
                }
                offsetModel.setValue(
                    offsetModel.getValue() + this.numberOfResultRows > resultCountModel.getValue()
                        ? resultCountModel.getValue() - this.numberOfResultRows
                        : offsetModel.getValue() + this.numberOfResultRows);
              })
              .build();
        })
        .addActionFactory((tableModel, selectionIndexModel, selectionModel, sortStateModel) -> {
          final BooleanModel enabledModel = new BooleanModel(
              offsetModel.getValue() + tableModel.size() < resultCountModel.getValue());
          tableModel.addTableModelListener(
              e -> enabledModel.set(offsetModel.getValue() + tableModel.size() < resultCountModel.getValue()));
          return new ConfigurableActionBuilder()
              .setIcon(net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.GO_LAST)
              .setEnabledDistributor(enabledModel)
              .setProcedure(component -> {
                if (selectionIndexModel.isEmpty()) {
                  selectedIndexModel.setValue(-1);
                } else {
                  selectedIndexModel.setValue(selectionIndexModel.getMinimum());
                }
                offsetModel.setValue(resultCountModel.getValue() - this.numberOfResultRows);
              })
              .build();
        })
        .addActionFactory((tableModel, selectionIndicesProvider, selectionModel, sortStateModel) -> {
          final BooleanModel enabledModel = new BooleanModel(false);
          selectionModel
              .addSelectionListener(e -> enabledModel.set(!e.getSource().isEmpty() && Desktop.isDesktopSupported()));
          return new ConfigurableActionBuilder()
              .setIcon(net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.NETWORK_TRANSMIT)
              .setTooltip(Messages.ckan_json_respone)
              .setEnabledDistributor(enabledModel)
              .setProcedure(component -> {
                final Desktop desktop = Desktop.getDesktop();
                final Dataset dataset = selectionModel.getSelectedObjects().iterator().next();
                final String urlString = description.getUrl() + "/3/action/package_show?id=" + dataset.getId(); //$NON-NLS-1$
                try {
                  final URI uri = new URI(urlString);
                  desktop.browse(uri);
                } catch (URISyntaxException | IOException exception) {
                  logger.log(ILevel.ERROR, exception.getMessage(), exception);
                }
              })
              .build();
        })
        .addActionFactory((tableModel, selectionIndicesProvider, selectionModel, sortStateModel) -> {
          final BooleanModel enabledModel = new BooleanModel(false);
          selectionModel.addSelectionListener(
              e -> enabledModel.set(
                  Desktop.isDesktopSupported()
                      && !e.getSource().isEmpty()
                      && !StringUtilities
                          .isNullOrEmpty(e.getSource().getSelectedObjects().iterator().next().getUrl())));
          return new ConfigurableActionBuilder()
              .setIcon(net.anwiba.commons.swing.icons.gnome.contrast.high.ContrastHightIcons.WEB_BROWSER)
              .setTooltip(Messages.browse_dataset)
              .setEnabledDistributor(enabledModel)
              .setProcedure(component -> {
                final Desktop desktop = Desktop.getDesktop();
                final Dataset dataset = selectionModel.getSelectedObjects().iterator().next();
                try {
                  final String url = dataset.getUrl().trim();
                  final URI uri = new URI(url);
                  desktop.browse(uri);
                } catch (URISyntaxException | IOException exception) {
                  logger.log(ILevel.ERROR, exception.getMessage(), exception);
                }
              })
              .build();
        })
        .setKeyListenerFactory(new IKeyListenerFactory() {

          @Override
          public KeyListener create(
              final IObjectTableModel tableModel,
              final ISelectionIndexModel selectionIndexModel,
              final ISelectionModel selectionModel,
              final IBooleanDistributor sortStateModel) {

            return new KeyAdapter() {

              @Override
              public void keyPressed(final KeyEvent event) {
                final int keyCode = event.getKeyCode();
                switch (keyCode) {
                  case KeyEvent.VK_PAGE_UP: {
                    event.consume();
                    if (tableModel.isEmpty()) {
                      selectedIndexModel.setValue(-1);
                    } else {
                      selectedIndexModel.setValue(tableModel.size() - 1);
                    }
                    offsetModel.setValue(
                        offsetModel.getValue() > DatasetTableFactory.this.numberOfResultRows
                            ? offsetModel.getValue() - DatasetTableFactory.this.numberOfResultRows
                            : 0);
                    return;
                  }
                  case KeyEvent.VK_PAGE_DOWN: {
                    event.consume();
                    if (!(offsetModel.getValue() + tableModel.size() < resultCountModel.getValue())) {
                      return;
                    }
                    if (tableModel.isEmpty()) {
                      selectedIndexModel.setValue(-1);
                    } else {
                      selectedIndexModel.setValue(0);
                    }
                    offsetModel.setValue(
                        offsetModel.getValue() + DatasetTableFactory.this.numberOfResultRows > resultCountModel
                            .getValue()
                                ? resultCountModel.getValue() - DatasetTableFactory.this.numberOfResultRows
                                : offsetModel.getValue() + DatasetTableFactory.this.numberOfResultRows);
                    return;
                  }
                }
              }
            };
          }
        })
        .build();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy