org.tuleap.mylyn.task.ui.internal.wizards.query.QueryFieldVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.tuleap.mylyn.task.ui.internal.wizards.query.QueryFieldVisitor.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Obeo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Obeo - initial API and implementation
 *******************************************************************************/
package org.tuleap.mylyn.task.ui.internal.wizards.query;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.eclipse.mylyn.commons.workbench.forms.DatePicker;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.tuleap.mylyn.task.core.internal.client.ITuleapQueryConstants;
import org.tuleap.mylyn.task.core.internal.model.config.AbstractTuleapField;
import org.tuleap.mylyn.task.core.internal.model.config.field.AbstractTuleapFieldVisitor;
import org.tuleap.mylyn.task.core.internal.model.config.field.AbstractTuleapSelectBox;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapArtifactLink;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapComputedValue;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapDate;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapFileUpload;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapFloat;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapInteger;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapMultiSelectBox;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapOpenList;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapSelectBox;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapSelectBoxItem;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapString;
import org.tuleap.mylyn.task.core.internal.model.config.field.TuleapText;
import org.tuleap.mylyn.task.core.internal.model.data.IQueryCriterion;
import org.tuleap.mylyn.task.core.internal.model.data.TuleapQueryCriterion;
import org.tuleap.mylyn.task.ui.internal.TuleapTasksUIPlugin;

/**
 * Visitor of tuleap fields to create the wizard's page.
 *
 * @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a>
 */
public class QueryFieldVisitor extends AbstractTuleapFieldVisitor {

    /**
     * The query form graphical elements.
     */
    private final List<AbstractTuleapCustomQueryElement<?>> elements;

    /**
     * Current query criteria.
     */
    private final JsonObject currentQueryCriteria;

    /**
     * The composite that contains the created fields in the wizard.
     */
    private final Composite group;

    /**
     * The Gson to use to deserialize query parameters.
     */
    private final Gson gson;

    /**
     * The wizard page.
     */
    private final TuleapCustomQueryPage page;

    /**
     * Constructor.
     *
     * @param group
     *            The parent composite.
     * @param gson
     *            The Gson to use to deserialize query parameters.
     * @param page
     *            The wizard page.
     */
    public QueryFieldVisitor(Composite group, Gson gson, final TuleapCustomQueryPage page) {
        this.group = group;
        this.gson = gson;
        this.page = page;
        IRepositoryQuery currentQuery = page.getQuery();
        String jsonCriteria = null;
        if (currentQuery != null) {
            jsonCriteria = currentQuery.getAttribute(ITuleapQueryConstants.QUERY_CUSTOM_CRITERIA);
        }
        JsonElement jsonElement;
        if (jsonCriteria != null) {
            jsonElement = new JsonParser().parse(jsonCriteria);
        } else {
            jsonElement = JsonNull.INSTANCE;
        }
        if (jsonElement.isJsonObject()) {
            currentQueryCriteria = jsonElement.getAsJsonObject();
        } else {
            currentQueryCriteria = new JsonObject();
        }
        elements = new ArrayList<AbstractTuleapCustomQueryElement<?>>();
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapArtifactLink)
     */
    @Override
    public void visit(TuleapArtifactLink field) {
        Text text = createGroupContentForString(field.getLabel(), field);
        loadValueForString(field, text);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapComputedValue)
     */
    @Override
    public void visit(TuleapComputedValue field) {
        Text text = createGroupContentForString(field.getLabel(), field);
        loadValueForString(field, text);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapDate)
     */
    @Override
    public void visit(TuleapDate field) {
        Label label = new Label(group, SWT.NONE);
        label.setText(field.getLabel());

        Combo combo = new Combo(group, SWT.SINGLE | SWT.READ_ONLY);
        combo.setItems(new String[] { IQueryCriterion.OP_LT, IQueryCriterion.OP_EQ, IQueryCriterion.OP_GT,
                IQueryCriterion.OP_BETWEEN, });
        combo.setText(IQueryCriterion.OP_LT);

        // Retrieval of values for existing query
        Calendar initialMin = null;
        Calendar initialMax = null;
        if (currentQueryCriteria.has(field.getName())) {
            JsonElement json = currentQueryCriteria.get(field.getName());
            // CHECKSTYLE:OFF
            Type criterionType = new TypeToken<TuleapQueryCriterion<Date[]>>() {
                // Nothing
            }.getType();
            // CHECKSTYLE:ON
            try {
                TuleapQueryCriterion<Date[]> criterion = gson.fromJson(json, criterionType);
                combo.setText(criterion.getOperator());
                Date[] dates = criterion.getValue();
                if (dates.length > 0 && dates[0] != null) {
                    initialMin = GregorianCalendar.getInstance();
                    initialMin.setTime(dates[0]);
                    if (dates.length > 1 && dates[1] != null) {
                        initialMax = GregorianCalendar.getInstance();
                        initialMax.setTime(dates[1]);
                    }
                }
                // CHECKSTYLE:OFF We need to prevent any exception to block here
            } catch (Exception e) {
                // CHECKSYLE:ON
                TuleapTasksUIPlugin.log(e, false);
            }

        }
        Composite composite = new Composite(group, SWT.NONE);
        GridLayout layout = new GridLayout(2, true);
        layout.marginLeft = 0;
        layout.marginRight = 0;
        layout.marginTop = 0;
        layout.marginBottom = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        DatePicker from = new DatePicker(composite, SWT.SINGLE | SWT.BORDER, "", false, 0); //$NON-NLS-1$
        from.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        final DatePicker to = new DatePicker(composite, SWT.SINGLE | SWT.BORDER, "", false, 0); //$NON-NLS-1$
        to.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        from.setDate(initialMin);
        to.setDate(initialMax);
        to.setVisible(IQueryCriterion.OP_BETWEEN.equals(combo.getText()));
        combo.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                if (IQueryCriterion.OP_BETWEEN.equals(((Combo) e.widget).getText())) {
                    to.setVisible(true);
                } else {
                    to.setVisible(false);
                }
            }
        });
        combo.addModifyListener(page.getModifyListener());
        from.addPickerSelectionListener(page.getSelectionListener());
        to.addPickerSelectionListener(page.getSelectionListener());
        elements.add(new TuleapDateQueryElement(field, combo, from, to));
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapFileUpload)
     */
    @Override
    public void visit(TuleapFileUpload field) {
        // Nothing to do for upload fields.
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapFloat)
     */
    @Override
    public void visit(TuleapFloat field) {
        Text text = createGroupContentForString(field.getLabel(), field);
        // CHECKSTYLE:OFF
        Type criterionType = new TypeToken<TuleapQueryCriterion<Double>>() {
            // Nothing
        }.getType();
        // CHECKSTYLE:ON
        if (currentQueryCriteria.has(field.getName())) {
            JsonElement json = currentQueryCriteria.get(field.getName());
            try {
                TuleapQueryCriterion<?> criterion = gson.fromJson(json, criterionType);
                text.setText(String.valueOf(criterion.getValue()));
                // CHECKSTYLE:OFF We need to prevent any exception to block here
            } catch (Exception e) {
                // CHECKSYLE:ON
                TuleapTasksUIPlugin.log(e, false);
            }
        }
        elements.add(new TuleapDoubleQueryElement(field, text));
        text.addModifyListener(page.getModifyListener());
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapInteger)
     */
    @Override
    public void visit(TuleapInteger field) {
        Text text = createGroupContentForString(field.getLabel(), field);
        // CHECKSTYLE:OFF
        Type criterionType = new TypeToken<TuleapQueryCriterion<Integer>>() {
            // Nothing
        }.getType();
        // CHECKSTYLE:ON
        if (currentQueryCriteria.has(field.getName())) {
            JsonElement json = currentQueryCriteria.get(field.getName());
            try {
                TuleapQueryCriterion<?> criterion = gson.fromJson(json, criterionType);
                text.setText(String.valueOf(criterion.getValue()));
                // CHECKSTYLE:OFF We need to prevent any exception to block here
            } catch (Exception e) {
                // CHECKSYLE:ON
                TuleapTasksUIPlugin.log(e, false);
            }
        }
        elements.add(new TuleapIntegerQueryElement(field, text));
        text.addModifyListener(page.getModifyListener());
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapMultiSelectBox)
     */
    @Override
    public void visit(TuleapMultiSelectBox field) {
        createGroupContentForSelectBox(field);
    }

    /**
     * Select items in a list widget.
     *
     * @param widget
     *            List widget
     * @param selectedItems
     *            Indexes of items to select in the widget
     */
    private void selectItems(org.eclipse.swt.widgets.List widget, List<Integer> selectedItems) {
        if (selectedItems == null || selectedItems.isEmpty()) {
            widget.setSelection(0);
        } else {
            int[] array = new int[selectedItems.size()];
            for (int i = 0; i < selectedItems.size(); i++) {
                array[i] = selectedItems.get(i).intValue();
            }
            widget.setSelection(array);
        }
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapOpenList)
     */
    @Override
    public void visit(TuleapOpenList field) {
        Text text = createGroupContentForString(field.getLabel(), field);
        loadValueForString(field, text);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapSelectBox)
     */
    @Override
    public void visit(TuleapSelectBox field) {
        createGroupContentForSelectBox(field);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapString)
     */
    @Override
    public void visit(TuleapString field) {
        Text text = createGroupContentForString(field.getLabel(), field);
        loadValueForString(field, text);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.tuleap.mylyn.task.core.internal.model.config.field.ITuleapFieldVisitor#visit(org.tuleap.mylyn.task.core.internal.model.config.field.TuleapText)
     */
    @Override
    public void visit(TuleapText field) {
        // Create a multi line text for each Tuleap text
        Label label = new Label(group, SWT.NONE);
        label.setText(field.getLabel());

        Combo combo = new Combo(group, SWT.SINGLE | SWT.READ_ONLY);
        combo.setItems(new String[] { ITuleapQueryOptions.StringOptions.OPTION_CONTAINS, });
        combo.setText(ITuleapQueryOptions.StringOptions.OPTION_CONTAINS);

        Text text = new Text(group, SWT.BORDER | SWT.MULTI);
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        text.setLayoutData(gridData);
        loadValueForString(field, text);
    }

    /**
     * Creates the dedicated type of widget for the Tuleap string kind field.
     *
     ** @param tuleapLabel
     *            The label
     * @param field
     *            The tuleap field
     * @return The Text widget created.
     */
    private Text createGroupContentForString(String tuleapLabel, AbstractTuleapField field) {
        Label label = new Label(group, SWT.NONE);
        label.setText(tuleapLabel);

        Combo combo = new Combo(group, SWT.SINGLE | SWT.READ_ONLY);
        combo.setItems(new String[] { ITuleapQueryOptions.StringOptions.OPTION_CONTAINS, });
        combo.setText(ITuleapQueryOptions.StringOptions.OPTION_CONTAINS);

        Text text = new Text(group, SWT.SINGLE | SWT.BORDER);
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        text.setLayoutData(gridData);
        return text;
    }

    /**
     * @param field
     * @param text
     */
    private void loadValueForString(AbstractTuleapField field, Text text) {
        // CHECKSTYLE:OFF
        Type criterionType = new TypeToken<TuleapQueryCriterion<String>>() {
            // Nothing
        }.getType();
        // CHECKSTYLE:ON
        if (currentQueryCriteria.has(field.getName())) {
            JsonElement json = currentQueryCriteria.get(field.getName());
            try {
                TuleapQueryCriterion<?> criterion = gson.fromJson(json, criterionType);
                text.setText(String.valueOf(criterion.getValue()));
                // CHECKSTYLE:OFF We need to prevent any exception to block here
            } catch (Exception e) {
                // CHECKSYLE:ON
                TuleapTasksUIPlugin.log(e, false);
            }
        }
        elements.add(new TuleapLiteralQueryElement(field, text));
    }

    /**
     * Creates the selection criterion for select boxes (single or multi).
     *
     * @param field
     *            The select box.
     */
    private void createGroupContentForSelectBox(AbstractTuleapSelectBox field) {
        Label label = new Label(group, SWT.NONE);
        label.setText(field.getLabel());

        Combo combo = new Combo(group, SWT.SINGLE | SWT.READ_ONLY);
        combo.setItems(new String[] { ITuleapQueryOptions.StringOptions.OPTION_CONTAINS, });
        combo.setText(ITuleapQueryOptions.StringOptions.OPTION_CONTAINS);

        org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(group,
                SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL | SWT.BORDER);
        List<String> items = new ArrayList<String>();
        items.add(""); //$NON-NLS-1$

        TuleapQueryCriterion<String[]> criterion = null;
        if (currentQueryCriteria.has(field.getName())) {
            JsonElement json = currentQueryCriteria.get(field.getName());
            // CHECKSTYLE:OFF
            Type boundCriterionType = new TypeToken<TuleapQueryCriterion<String[]>>() {
                // Nothing
            }.getType();
            // CHECKSTYLE:ON
            try {
                criterion = gson.fromJson(json, boundCriterionType);
                // CHECKSTYLE:OFF We need to prevent any exception to block here
            } catch (Exception e) {
                // CHECSKTYLE:ON
                TuleapTasksUIPlugin.log(e, false);
            }
        }

        // We need to work with criteria values instead of internal Tuleap integer IDs
        int index = 0;
        List<Integer> selectedItems = new ArrayList<Integer>();
        Collection<TuleapSelectBoxItem> selectBoxItems = field.getItems();
        for (TuleapSelectBoxItem item : selectBoxItems) {
            index++;
            String itemLabel = item.getLabel();
            items.add(itemLabel);
            if (criterion != null) {
                try {
                    for (String criterionId : criterion.getValue()) {
                        if (itemLabel.equals(criterionId)) {
                            selectedItems.add(Integer.valueOf(index));
                            break;
                        }
                    }
                    // CHECKSTYLE:OFF We need to prevent any exception to block here
                } catch (Exception e) {
                    // CHECSKTYLE:ON
                    TuleapTasksUIPlugin.log(e, false);
                }
            }
        }
        list.setItems(items.toArray(new String[items.size()]));
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        list.setLayoutData(gridData);

        selectItems(list, selectedItems);
        combo.addModifyListener(page.getModifyListener());

        elements.add(new TuleapSelectBoxQueryElement(field, list));
    }

    /**
     * Provides a read-only view of the query elements built by this visitor.
     *
     * @return An unmodifiable list of the query elements.
     */
    public List<AbstractTuleapCustomQueryElement<?>> getQueryElements() {
        return Collections.unmodifiableList(elements);
    }
}