/******************************************************************************* * Copyright (c) 2013 hangum. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * hangum - initial API and implementation ******************************************************************************/ package com.hangum.tadpole.mongodb.core.editors.mapreduce; import org.apache.log4j.Logger; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.EditorPart; import com.hangum.tadpole.ace.editor.core.widgets.TadpoleEditorWidget; import com.hangum.tadpole.commons.exception.dialog.ExceptionDetailsErrorDialog; import com.hangum.tadpole.commons.google.analytics.AnalyticCaller; import com.hangum.tadpole.commons.libs.core.message.CommonMessages; import com.hangum.tadpole.commons.util.TadpoleWidgetUtils; import com.hangum.tadpole.engine.query.dao.system.UserDBDAO; import com.hangum.tadpole.engine.utils.EditorDefine; import com.hangum.tadpole.mongodb.core.Activator; import com.hangum.tadpole.mongodb.core.composite.result.MongodbResultComposite; import com.hangum.tadpole.mongodb.core.query.MongoDBQuery; import com.hangum.tadpole.mongodb.core.utils.CollectionUtils; import com.mongodb.BasicDBObject; import com.mongodb.CommandResult; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.MapReduceCommand; import com.mongodb.MapReduceCommand.OutputType; import com.mongodb.util.JSON; /** * MapReduce editor * * @author hangum * */ public class MapReduceEditor extends EditorPart { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(MapReduceEditor.class); public static final String ID = "com.hangum.tadpole.mongodb.core.ext.editor.mapreduce"; private String TEMPLATE_MAP_SRC = "function() {\r" + TadpoleWidgetUtils.TAB_CONETNT + " emit(this.user_id, 1); \r}"; private String TEMPLATE_REDUCE_SRC = "function(k,values) {\r" + TadpoleWidgetUtils.TAB_CONETNT + " return 1; \r}"; private String TEMPLATE_FINALIZE_SRC = "";//"function Finalize(key, reduced) {\r" + TadpoleWidgetUtils.TAB_CONETNT + " return reduced; \r}"; /** 초기에 선택된 collection name */ private UserDBDAO userDB; private String initColName = ""; private TadpoleEditorWidget textMap; private TadpoleEditorWidget textReduce; private TadpoleEditorWidget textFinalize; // output private Combo comboOutputType; private TadpoleEditorWidget textQuery; private Text textLimit; private TadpoleEditorWidget textSort; private Text textOutputTarget; private Button btnSharded; private Button btnNoneAtomic; private Button btnJsMode; /** 쿼리 결과 출력 */ private MongodbResultComposite compositeResult ; public MapReduceEditor() { super(); } @Override public void createPartControl(Composite parent) { GridLayout gl_parent = new GridLayout(1, false); gl_parent.verticalSpacing = 0; gl_parent.horizontalSpacing = 0; gl_parent.marginHeight = 0; gl_parent.marginWidth = 0; parent.setLayout(gl_parent); SashForm sashFormMain = new SashForm(parent, SWT.VERTICAL); sashFormMain.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Composite compositeMapReduceFinalize = new Composite(sashFormMain, SWT.NONE); GridLayout gl_compositeMapReduceFinalize = new GridLayout(1, false); gl_compositeMapReduceFinalize.verticalSpacing = 1; gl_compositeMapReduceFinalize.horizontalSpacing = 1; gl_compositeMapReduceFinalize.marginHeight = 1; gl_compositeMapReduceFinalize.marginWidth = 1; compositeMapReduceFinalize.setLayout(gl_compositeMapReduceFinalize); SashForm sashFormMRF = new SashForm(compositeMapReduceFinalize, SWT.NONE); sashFormMRF.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Group grpMap = new Group(sashFormMRF, SWT.NONE); grpMap.setText("Map"); GridLayout gl_grpMap = new GridLayout(1, false); gl_grpMap.verticalSpacing = 1; gl_grpMap.horizontalSpacing = 1; gl_grpMap.marginHeight = 1; gl_grpMap.marginWidth = 1; grpMap.setLayout(gl_grpMap); String strAssist = CollectionUtils.getAssistList(userDB, initColName); textMap = new TadpoleEditorWidget(grpMap, SWT.BORDER, EditorDefine.EXT_JSON, "", strAssist); textMap.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Group grpReduce = new Group(sashFormMRF, SWT.NONE); grpReduce.setText("Reduce"); GridLayout gl_grpReduce = new GridLayout(1, false); gl_grpReduce.verticalSpacing = 1; gl_grpReduce.horizontalSpacing = 1; gl_grpReduce.marginHeight = 1; gl_grpReduce.marginWidth = 1; grpReduce.setLayout(gl_grpReduce); textReduce = new TadpoleEditorWidget(grpReduce, SWT.BORDER, EditorDefine.EXT_JSON, "", strAssist); textReduce.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Group grpFinalize = new Group(sashFormMRF, SWT.NONE); grpFinalize.setText("Finalize"); GridLayout gl_grpFinalize = new GridLayout(1, false); gl_grpFinalize.verticalSpacing = 1; gl_grpFinalize.horizontalSpacing = 1; gl_grpFinalize.marginHeight = 1; gl_grpFinalize.marginWidth = 1; grpFinalize.setLayout(gl_grpFinalize); textFinalize = new TadpoleEditorWidget(grpFinalize, SWT.BORDER, EditorDefine.EXT_JSON, "", strAssist); textFinalize.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); sashFormMRF.setWeights(new int[] {4, 4, 2}); Composite compositeInOut = new Composite(sashFormMain, SWT.NONE); GridLayout gl_compositeInOut = new GridLayout(1, false); gl_compositeInOut.verticalSpacing = 1; gl_compositeInOut.horizontalSpacing = 1; gl_compositeInOut.marginHeight = 1; gl_compositeInOut.marginWidth = 1; compositeInOut.setLayout(gl_compositeInOut); SashForm sashForm = new SashForm(compositeInOut, SWT.NONE); sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Group grpInput = new Group(sashForm, SWT.NONE); grpInput.setText("Input"); GridLayout gl_grpInput = new GridLayout(2, false); gl_grpInput.verticalSpacing = 2; gl_grpInput.horizontalSpacing = 2; gl_grpInput.marginHeight = 2; gl_grpInput.marginWidth = 2; grpInput.setLayout(gl_grpInput); Label lblQuery = new Label(grpInput, SWT.NONE); lblQuery.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblQuery.setText("Query"); textQuery = new TadpoleEditorWidget(grpInput, SWT.BORDER, EditorDefine.EXT_JSON, "", strAssist); textQuery.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Label lblSort = new Label(grpInput, SWT.NONE); lblSort.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblSort.setText("Sort"); textSort = new TadpoleEditorWidget(grpInput, SWT.BORDER, EditorDefine.EXT_JSON, "", strAssist); textSort.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); Label lblLimit = new Label(grpInput, SWT.NONE); lblLimit.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblLimit.setText("Limit"); textLimit = new Text(grpInput, SWT.BORDER); textLimit.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); Group grpOutput_1 = new Group(sashForm, SWT.NONE); grpOutput_1.setText("Output"); GridLayout gl_grpOutput_1 = new GridLayout(2, false); gl_grpOutput_1.verticalSpacing = 2; gl_grpOutput_1.horizontalSpacing = 2; gl_grpOutput_1.marginHeight = 2; gl_grpOutput_1.marginWidth = 2; grpOutput_1.setLayout(gl_grpOutput_1); Label lblType = new Label(grpOutput_1, SWT.NONE); lblType.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblType.setText("Type"); comboOutputType = new Combo(grpOutput_1, SWT.READ_ONLY); comboOutputType.setEnabled(false); comboOutputType.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); for (OutputType outputType : MapReduceCommand.OutputType.values()) { comboOutputType.add(outputType.toString()); comboOutputType.setData(outputType.toString(), outputType); } comboOutputType.select(3); Label lblOutput = new Label(grpOutput_1, SWT.NONE); lblOutput.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); lblOutput.setText("Output"); textOutputTarget = new Text(grpOutput_1, SWT.BORDER); textOutputTarget.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); new Label(grpOutput_1, SWT.NONE); btnSharded = new Button(grpOutput_1, SWT.CHECK); btnSharded.setText("Sharded "); new Label(grpOutput_1, SWT.NONE); btnNoneAtomic = new Button(grpOutput_1, SWT.CHECK); btnNoneAtomic.setText("None Atomic"); new Label(grpOutput_1, SWT.NONE); btnJsMode = new Button(grpOutput_1, SWT.CHECK); btnJsMode.setText("JS Mode"); new Label(grpOutput_1, SWT.NONE); Button btnExecute = new Button(grpOutput_1, SWT.NONE); btnExecute.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { try { executeMapReduce(); } catch (Exception e1) { logger.error("MapReduce Error", e1); //$NON-NLS-1$ Status errStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e1.getMessage(), e1); //$NON-NLS-1$ ExceptionDetailsErrorDialog.openError(null,CommonMessages.get().Error, "MapReduce Search exception", errStatus); //$NON-NLS-1$ //$NON-NLS-2$ } } }); btnExecute.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); btnExecute.setText("Search"); sashForm.setWeights(new int[] {1, 1}); compositeResult = new MongodbResultComposite(sashFormMain, SWT.NONE, userDB, initColName, false); compositeResult.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); GridLayout gl_compositeResult = new GridLayout(1, false); gl_compositeResult.verticalSpacing = 0; gl_compositeResult.horizontalSpacing = 0; gl_compositeResult.marginHeight = 0; gl_compositeResult.marginWidth = 0; compositeResult.setLayout(gl_compositeResult); sashFormMain.setWeights(new int[] {40, 30, 30}); initUI(); // google analytic AnalyticCaller.track(this.getClass().getName()); } /** * execute map reduce */ private void executeMapReduce() throws Exception { String strMap = textMap.getText(); String strReduce = textReduce.getText(); String strFinilize = textFinalize.getText(); String strOutputTarget = textOutputTarget.getText(); MapReduceCommand.OutputType outputType = (MapReduceCommand.OutputType)comboOutputType.getData(comboOutputType.getText()); DBObject dbQuery = null; if(!"".equals(textQuery.getText())) dbQuery = (DBObject) JSON.parse(textQuery.getText()); DBObject dbSort = null; if(!"".equals(textSort.getText())) dbSort = (DBObject) JSON.parse(textSort.getText()); // 쿼리 합니다. DBCollection dbCol = MongoDBQuery.findCollection(userDB, initColName); MapReduceCommand mrCmd = new MapReduceCommand(dbCol, strMap, strReduce, strOutputTarget, outputType, dbQuery); if(!"".equals(strFinilize)) mrCmd.setFinalize(strFinilize); if(dbSort != null) mrCmd.setSort(dbSort); if(getLimit() > 0) mrCmd.setLimit(getLimit()); if(btnJsMode.getSelection()) { mrCmd.setJsMode(true); } final BasicDBObject searchObj = (BasicDBObject)mrCmd.toDBObject(); if(btnSharded.getSelection()) ((BasicDBObject)searchObj.get("out")).put("sharded", true); if(btnNoneAtomic.getSelection()) ((BasicDBObject)searchObj.get("out")).put("nonAtomic", true); goMapReduce(dbCol, searchObj, outputType); } /** * 검색합니다. * * @param dbCollection * @param cmdSearchObj * @param outputType */ CommandResult cmdResult = null; // MapReduceOutput mrOutput = null; private void goMapReduce(final DBCollection dbCol, final BasicDBObject basicObj, final MapReduceCommand.OutputType mrOType) { Job job = new Job("MapReduce search job") { //$NON-NLS-1$ @Override public IStatus run(IProgressMonitor monitor) { monitor.beginTask("Starting JSON query...", IProgressMonitor.UNKNOWN); //$NON-NLS-1$ try { // if(mrOType == MapReduceCommand.OutputType.INLINE) { // cmdResult = dbCol.getDB().command(basicObj, dbCol.getOptions()); // cmdResult.throwOnError(); // mrOutput = new MapReduceOutput(dbCol, basicObj, cmdResult); // } else { cmdResult = dbCol.getDB().command(basicObj); // cmdResult.throwOnError(); // mrOutput = new MapReduceOutput(dbCol, basicObj, cmdResult); // } if(!cmdResult.ok()) { throw cmdResult.getException(); } } catch (Exception e) { logger.error("mapreduce exception", e); //$NON-NLS-1$ return new Status(Status.WARNING,Activator.PLUGIN_ID, "mapreduce " + e.getMessage()); //$NON-NLS-1$ } finally { monitor.done(); } return Status.OK_STATUS; } }; // job의 event를 처리해 줍니다. job.addJobChangeListener(new JobChangeAdapter() { public void done(IJobChangeEvent event) { final IJobChangeEvent jobEvent = event; getSite().getShell().getDisplay().asyncExec(new Runnable() { public void run() { if(jobEvent.getResult().isOK()) { try { Iterable<DBObject> iteResult = (Iterable<DBObject>)cmdResult.get("results"); compositeResult.refreshDBView(iteResult, 0); compositeResult.setResult(); } catch(Exception e) { logger.error("MapReduce Error", e); //$NON-NLS-1$ Status errStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e); //$NON-NLS-1$ ExceptionDetailsErrorDialog.openError(null,CommonMessages.get().Error, "MapReduce execute exception", errStatus); //$NON-NLS-1$ //$NON-NLS-2$ } } else { // compositeResult.errorView(jobEvent.getResult().getMessage()); } } }); // end display.asyncExec } // end done }); // end job job.setName(userDB.getDisplay_name()); job.setUser(true); job.schedule(); } private int getLimit() { try { return Integer.parseInt(textLimit.getText()); } catch(Exception e) { return 0; } } /** * ui초기화 작업을 합니다. */ private void initUI() { // textMap.setText(TEMPLATE_MAP_SRC); // textReduce.setText(TEMPLATE_REDUCE_SRC); // textFinalize.setText(TEMPLATE_FINALIZE_SRC); textMap.setFocus(); // google analytic AnalyticCaller.track(MapReduceEditor.ID); } @Override public void setFocus() { } @Override public void doSave(IProgressMonitor monitor) { } @Override public void doSaveAs() { } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); MapReduceEditorInput editInput = (MapReduceEditorInput)input; setPartName(editInput.getName()); this.initColName = editInput.getColname(); this.userDB = editInput.getUserDB(); } @Override public boolean isDirty() { return false; } @Override public boolean isSaveAsAllowed() { return false; } }