Java tutorial
/** * Copyright (c) 2016 Modus Operandi, Inc. * * This 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 3 of the License, or 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 Lesser General Public License for more * details. A copy of the GNU Lesser General Public License is distributed along * with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package com.modusoperandi.dragonfly.widgets.chart; import com.carrotsearch.hppc.ObjectLookupContainer; import com.google.common.collect.UnmodifiableIterator; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.RadioChoice; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.PropertyModel; import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.Client; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; /** * The Class HeatMapSettingsPanel - Supports adding and removing data */ public class SettingsPanel extends Panel { public static final String XY = "X/Y"; public static final String FACET_BAR = "Occurance"; public static final String SERIES_LINE = "Series"; public static final String FACET_PIE = "Pie"; public static final String TIMEWHEEL = "Time Wheel"; public static final String HEAT_MAP_RING_MAP = "Heat Map Ring Map"; private static final Logger LOGGER = Logger.getLogger(SettingsPanel.class.getName()); private static transient Client esClient = null; private static final long serialVersionUID = 1L; private static ImmutableOpenMap<String, MappingMetaData> esGetMappings(final String indexName) { final ClusterStateResponse clusterStateResponse = getEsClient().admin().cluster().prepareState().execute() .actionGet(); return clusterStateResponse.getState().getMetaData().index(indexName).getMappings(); } /** * Gets the Elasticsearch client. * * @return the Elasticsearch client */ private static Client getEsClient() { // //////////// // Remote if (esClient == null) { try { final Settings settings = Settings.settingsBuilder() .put("node.name", "DRAGONFLY_" + Long.toString(Thread.currentThread().getId())) .put("cluster.name", "DRAGONFLY").build(); esClient = new TransportClient.Builder().settings(settings).build().addTransportAddress( new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300)); } catch (UnknownHostException ex) { LOGGER.log(Level.SEVERE, null, ex); } } return esClient; } private Map<String, String> configuration; private WebMarkupContainer contentDiv; private final WebMarkupContainer indexDiv; private final List<String> indexList = new LinkedList<>(); private String indexName; private final List<String> numericFieldsList = new LinkedList<>(); private final List<String> allFieldsList = new LinkedList<>(); private final List<String> timeFieldsList = new LinkedList<>(); private final List<String> locationFieldsList = new LinkedList<>(); private boolean ok = false; private final DropDownChoice<?> selectIndex; private String type = XY; private String xField; private DropDownChoice<?> xSelectField; private DropDownChoice<?> countSelectField; private DropDownChoice<?> pieCountSelectField; private DropDownChoice<?> maxItemsField; private DropDownChoice<?> pieMaxItemsField; private WebMarkupContainer xyDiv; private String yField; private DropDownChoice<?> ySelectField; private String countField; private String pieCountField; private WebMarkupContainer facetBarDiv; private WebMarkupContainer facetPieDiv; private String maxItems = "20"; private String pieMaxItems = "20"; private String seriesXField; private DropDownChoice<?> seriesXSelectField; private String seriesYField; private DropDownChoice<?> seriesYSelectField; private WebMarkupContainer seriesDiv; private String twTimeField; private String twTimeScaleField = "Days/Hours"; private DropDownChoice<?> twTimeScaleSelectField; private DropDownChoice<?> twTimeSelectField; private DropDownChoice<?> twContrastScaleSelectField; private String twContrastScaleField = "0"; private WebMarkupContainer timewheelDiv; private WebMarkupContainer hmrmDiv; private String hmrmTimeField; private String hmrmTimeScaleField = "Years"; private DropDownChoice<?> hmrmTimeScaleSelectField; private DropDownChoice<?> hmrmTimeSelectField; private DropDownChoice<?> hmrmLocationSelectField; private String hmrmLocationField; private DropDownChoice<?> hmrmLabelSelectField; private String hmrmLabelField; /** * Instantiates a new settings page. * * @param id * @param modalWindow */ public SettingsPanel(final String id, final ModalWindow modalWindow) { super(id); configuration = new HashMap<>(); final Form<?> dataForm = new Form<>("dataForm"); add(dataForm); contentDiv = new WebMarkupContainer("contentDiv"); contentDiv.setOutputMarkupId(true); dataForm.add(contentDiv); // //////////////////////////// // Type final RadioChoice<String> typeField = new RadioChoice<String>("type", new PropertyModel<>(this, "type"), Arrays.asList( new String[] { XY, FACET_BAR, SERIES_LINE, FACET_PIE, TIMEWHEEL, HEAT_MAP_RING_MAP })) { private static final long serialVersionUID = 1L; @Override public String getSuffix() { return ""; } }; typeField.add(new AjaxFormChoiceComponentUpdatingBehavior() { private static final long serialVersionUID = 1L; @Override protected void onUpdate(final AjaxRequestTarget target) { type = getComponent().getDefaultModelObjectAsString(); showDivs(); target.add(contentDiv); } }); contentDiv.add(typeField); // //////////////////////////// // Index Name populateIndices(); indexDiv = new WebMarkupContainer("indexDiv"); indexDiv.setOutputMarkupId(true); contentDiv.add(indexDiv); selectIndex = new DropDownChoice<>("dataSet", new PropertyModel<String>(this, "indexName"), indexList); selectIndex.add(new AjaxFormComponentUpdatingBehavior("focus") { private static final long serialVersionUID = 2981822623630720652L; @Override protected void onUpdate(final AjaxRequestTarget target) { if (populateIndices()) { target.add(selectIndex); } } }); selectIndex.add(new AjaxFormComponentUpdatingBehavior("change") { private static final long serialVersionUID = 2981822623630720652L; @Override protected void onUpdate(final AjaxRequestTarget target) { populateFieldsList(numericFieldsList, "double"); populateFieldsList(allFieldsList, null); populateFieldsList(timeFieldsList, "date"); populateFieldsList(locationFieldsList, "geo_point"); if (numericFieldsList.size() > 0) { seriesYField = numericFieldsList.get(0); xField = numericFieldsList.get(0); yField = numericFieldsList.get(0); } if (allFieldsList.size() > 0) { countField = allFieldsList.get(0); pieCountField = allFieldsList.get(0); seriesXField = allFieldsList.get(0); hmrmLabelField = allFieldsList.get(0); } if (timeFieldsList.size() > 0) { twTimeField = timeFieldsList.get(0); hmrmTimeField = timeFieldsList.get(0); } if (locationFieldsList.size() > 0) { hmrmLocationField = locationFieldsList.get(0); } target.add(xSelectField); target.add(ySelectField); target.add(countSelectField); target.add(seriesXSelectField); target.add(seriesYSelectField); target.add(pieCountSelectField); target.add(twTimeSelectField); target.add(hmrmTimeSelectField); target.add(hmrmLocationSelectField); target.add(hmrmLabelSelectField); } }); indexDiv.add(selectIndex); // //////////////////////////// // Type Panels configureXyDiv(); configureFacetBarDiv(); configureSeriesDiv(); configureFacetPieDiv(); configureTimewheelDiv(); configureHeatMapRingMapDiv(); showDivs(); // //////////////////////////// // Buttons dataForm.add(new AjaxButton("okButton") { private static final long serialVersionUID = 1L; @Override protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { configuration.clear(); configuration.put("Index", indexName); configuration.put("Type", type); switch (type) { case XY: configuration.put("X", xField); configuration.put("Y", yField); break; case FACET_BAR: configuration.put("CountField", countField); configuration.put("MaxItems", maxItems); break; case SERIES_LINE: configuration.put("X", seriesXField); configuration.put("Y", seriesYField); break; case FACET_PIE: configuration.put("CountField", pieCountField); configuration.put("MaxItems", pieMaxItems); break; case TIMEWHEEL: configuration.put("TimeScale", twTimeScaleField); configuration.put("TimeField", twTimeField); configuration.put("ContrastScale", twContrastScaleField); break; case HEAT_MAP_RING_MAP: configuration.put("TimeScale", hmrmTimeScaleField); configuration.put("TimeField", hmrmTimeField); configuration.put("LocationField", hmrmLocationField); configuration.put("LabelField", hmrmLabelField); break; } ok = true; modalWindow.close(target); } }); dataForm.add(new AjaxButton("cancelButton") { private static final long serialVersionUID = 1L; @Override protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { configuration.clear(); ok = false; modalWindow.close(target); } }); } public Map<String, String> getConfiguration() { return configuration; } public boolean isOk() { return ok; } private void configureXyDiv() { xyDiv = new WebMarkupContainer("xyDiv"); xyDiv.setOutputMarkupId(true); contentDiv.add(xyDiv); xSelectField = new DropDownChoice<>("xField", new PropertyModel<String>(this, "xField"), numericFieldsList); xSelectField.setOutputMarkupId(true); xyDiv.add(xSelectField); ySelectField = new DropDownChoice<>("yField", new PropertyModel<String>(this, "yField"), numericFieldsList); ySelectField.setOutputMarkupId(true); xyDiv.add(ySelectField); } private void configureSeriesDiv() { seriesDiv = new WebMarkupContainer("seriesDiv"); seriesDiv.setOutputMarkupId(true); contentDiv.add(seriesDiv); seriesXSelectField = new DropDownChoice<>("seriesXField", new PropertyModel<String>(this, "seriesXField"), timeFieldsList); seriesXSelectField.setOutputMarkupId(true); seriesDiv.add(seriesXSelectField); seriesYSelectField = new DropDownChoice<>("seriesYField", new PropertyModel<String>(this, "seriesYField"), numericFieldsList); seriesYSelectField.setOutputMarkupId(true); seriesDiv.add(seriesYSelectField); } private void configureFacetBarDiv() { facetBarDiv = new WebMarkupContainer("facetBarDiv"); facetBarDiv.setOutputMarkupId(true); contentDiv.add(facetBarDiv); countSelectField = new DropDownChoice<>("countField", new PropertyModel<String>(this, "countField"), allFieldsList); countSelectField.setOutputMarkupId(true); facetBarDiv.add(countSelectField); maxItemsField = new DropDownChoice<>("maxItems", new PropertyModel<String>(this, "maxItems"), Arrays.asList(new String[] { "5", "10", "20", "50" })); maxItemsField.setOutputMarkupId(true); facetBarDiv.add(maxItemsField); } private void configureFacetPieDiv() { facetPieDiv = new WebMarkupContainer("facetPieDiv"); facetPieDiv.setOutputMarkupId(true); contentDiv.add(facetPieDiv); pieCountSelectField = new DropDownChoice<>("pieCountField", new PropertyModel<String>(this, "pieCountField"), allFieldsList); pieCountSelectField.setOutputMarkupId(true); facetPieDiv.add(pieCountSelectField); pieMaxItemsField = new DropDownChoice<>("pieMaxItems", new PropertyModel<String>(this, "pieMaxItems"), Arrays.asList(new String[] { "5", "10", "20", "50" })); pieMaxItemsField.setOutputMarkupId(true); facetPieDiv.add(pieMaxItemsField); } private void configureTimewheelDiv() { timewheelDiv = new WebMarkupContainer("timewheelDiv"); timewheelDiv.setOutputMarkupId(true); contentDiv.add(timewheelDiv); twTimeScaleSelectField = new DropDownChoice<>("twTimeScaleField", new PropertyModel<String>(this, "twTimeScaleField"), Arrays.asList(new String[] { "Days/Hours", "Months/Days" })); timewheelDiv.add(twTimeScaleSelectField); twTimeSelectField = new DropDownChoice<>("twTimeField", new PropertyModel<String>(this, "twTimeField"), timeFieldsList); twTimeSelectField.setOutputMarkupId(true); timewheelDiv.add(twTimeSelectField); twContrastScaleSelectField = new DropDownChoice<>("twContrastScaleField", new PropertyModel<String>(this, "twContrastScaleField"), Arrays.asList( new String[] { "-90%", "-75%", "-50%", "-25%", "0", "+25%", "+50%", "+75%", "+90%" })); timewheelDiv.add(twContrastScaleSelectField); } private void configureHeatMapRingMapDiv() { hmrmDiv = new WebMarkupContainer("heatMapRingMapDiv"); hmrmDiv.setOutputMarkupId(true); contentDiv.add(hmrmDiv); hmrmTimeScaleSelectField = new DropDownChoice<>("hmrmTimeScaleField", new PropertyModel<String>(this, "hmrmTimeScaleField"), Arrays.asList(new String[] { "Years", "Months", "Days", "Hours", "Minutes" })); hmrmDiv.add(hmrmTimeScaleSelectField); hmrmTimeSelectField = new DropDownChoice<>("hmrmTimeField", new PropertyModel<String>(this, "hmrmTimeField"), timeFieldsList); hmrmTimeSelectField.setOutputMarkupId(true); hmrmDiv.add(hmrmTimeSelectField); hmrmLocationSelectField = new DropDownChoice<>("hmrmLocationField", new PropertyModel<String>(this, "hmrmLocationField"), locationFieldsList); hmrmLocationSelectField.setOutputMarkupId(true); hmrmDiv.add(hmrmLocationSelectField); hmrmLabelSelectField = new DropDownChoice<>("hmrmLabelField", new PropertyModel<String>(this, "hmrmLabelField"), allFieldsList); hmrmLabelSelectField.setOutputMarkupId(true); hmrmDiv.add(hmrmLabelSelectField); } private SearchResponse esMakeQuery() { final SearchRequestBuilder search = getEsClient().prepareSearch(indexName); search.setSearchType(SearchType.DFS_QUERY_THEN_FETCH); return search.execute().actionGet(); } /** * Populate field lists from the ES index mapping. */ private void populateFieldsList(final List<String> list, final String desiredType) { list.clear(); try { esMakeQuery(); final ImmutableOpenMap<String, MappingMetaData> typeMappings = esGetMappings(indexName); final UnmodifiableIterator<MappingMetaData> it = typeMappings.valuesIt(); while (it.hasNext()) { final MappingMetaData mapping = it.next(); @SuppressWarnings("unchecked") final Map<String, Object> fields = ((Map<String, Object>) mapping.getSourceAsMap() .get("properties")); fields.keySet().stream().forEach((y) -> { @SuppressWarnings("unchecked") final String fieldType = ((Map<String, Object>) fields.get(y)).get("type").toString(); if ((desiredType == null) || fieldType.equals(desiredType)) { list.add(y); } }); } } catch (final IOException e) { LOGGER.log(Level.SEVERE, e.getMessage(), e); } } private boolean populateIndices() { ObjectLookupContainer<String> mapAl = getEsClient().admin().cluster().prepareState().execute().actionGet() .getState().getMetaData().indices().keys(); final Object keyAry[] = mapAl.toArray(); boolean changed = (indexList.size() != keyAry.length); int i = 0; while ((i < indexList.size()) && (i < keyAry.length) && !changed) { changed = !indexList.get(i).equals(keyAry[i]); i++; } if (changed) { indexList.clear(); for (final Object index : keyAry) { indexList.add(index.toString()); } } return changed; } private void showDivs() { switch (type) { case XY: indexDiv.setVisible(true); xyDiv.setVisible(true); facetBarDiv.setVisible(false); seriesDiv.setVisible(false); facetPieDiv.setVisible(false); timewheelDiv.setVisible(false); hmrmDiv.setVisible(false); break; case FACET_BAR: indexDiv.setVisible(true); xyDiv.setVisible(false); facetBarDiv.setVisible(true); seriesDiv.setVisible(false); facetPieDiv.setVisible(false); timewheelDiv.setVisible(false); hmrmDiv.setVisible(false); break; case SERIES_LINE: indexDiv.setVisible(true); xyDiv.setVisible(false); facetBarDiv.setVisible(false); seriesDiv.setVisible(true); facetPieDiv.setVisible(false); timewheelDiv.setVisible(false); hmrmDiv.setVisible(false); break; case FACET_PIE: indexDiv.setVisible(true); xyDiv.setVisible(false); facetBarDiv.setVisible(false); seriesDiv.setVisible(false); facetPieDiv.setVisible(true); timewheelDiv.setVisible(false); hmrmDiv.setVisible(false); break; case TIMEWHEEL: indexDiv.setVisible(true); xyDiv.setVisible(false); facetBarDiv.setVisible(false); seriesDiv.setVisible(false); facetPieDiv.setVisible(false); timewheelDiv.setVisible(true); hmrmDiv.setVisible(false); break; case HEAT_MAP_RING_MAP: indexDiv.setVisible(true); xyDiv.setVisible(false); facetBarDiv.setVisible(false); seriesDiv.setVisible(false); facetPieDiv.setVisible(false); timewheelDiv.setVisible(false); hmrmDiv.setVisible(true); break; } } }