package enterpriseapp.ui.reports; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.hibernate.Query; import org.hibernate.metadata.ClassMetadata; import org.hibernate.transform.AliasToEntityMapResultTransformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vaadin.addon.tableexport.ExcelExport; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.ItemClickEvent; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.event.ShortcutAction.ModifierKey; import com.vaadin.server.Resource; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.CustomComponent; import com.vaadin.ui.Field; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalSplitPanel; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Select; import com.vaadin.ui.Table; import com.vaadin.ui.TextArea; import com.vaadin.ui.TextField; import com.vaadin.ui.Tree; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalSplitPanel; import enterpriseapp.Utils; import enterpriseapp.hibernate.Db; import enterpriseapp.ui.Constants; /** * A UI component to test HQL queries. * * @author Alejandro Duarte * */ public class HqlQueryBrowser extends CustomComponent implements ClickListener, ItemClickListener, Handler { private static final long serialVersionUID = 1L; private static Logger logger = LoggerFactory.getLogger(HqlQueryBrowser.class); public final Action ACTION_EXPORT_TO_EXCEL = new Action(Constants.uiExportToExcel); protected HorizontalSplitPanel layout = new HorizontalSplitPanel(); protected VerticalLayout leftLayout = new VerticalLayout(); protected Tree tree = new Tree(); protected VerticalSplitPanel rightLayout = new VerticalSplitPanel(); protected HorizontalSplitPanel querySplit = new HorizontalSplitPanel(); protected VerticalLayout queryLayout = new VerticalLayout(); protected HorizontalLayout queryActionsLayout = new HorizontalLayout(); protected Label maxResultsLabel = new Label(Constants.uiMaxResults); protected TextField maxResultsTextField = new TextField(); protected Button executeQueryButton = new Button(Constants.uiExecute); protected Button clearQueryButton = new Button(Constants.uiClear); protected Label queryLabel = new Label(Constants.uiHqlQuery + ":"); protected TextArea queryTextArea = new TextArea(); protected VerticalLayout paramsLayout = new VerticalLayout(); protected Label paramsLabel = new Label(Constants.uiParameters); protected VerticalLayout paramsFieldsLayout = new VerticalLayout(); protected HorizontalLayout paramsActionsLayout = new HorizontalLayout(); protected Button addParamButton = new Button(Constants.uiAdd); protected Button deleteParamButton = new Button(Constants.uiDelete); protected ArrayList<TextField> paramsValues = new ArrayList<TextField>(); protected ArrayList<Select> paramsTypes = new ArrayList<Select>(); protected VerticalLayout tableLayout = new VerticalLayout(); protected Table table; protected Resource databaseIcon; protected Resource entityIcon; protected Resource columnIcon; public HqlQueryBrowser() { this(null, null, null); } public HqlQueryBrowser(Resource databaseIcon, Resource entityIcon, Resource columnIcon) { this.databaseIcon = databaseIcon; this.entityIcon = entityIcon; this.columnIcon = columnIcon; leftLayout.setMargin(true); leftLayout.addComponent(tree); tree.addItem(0); tree.setItemCaption(0, Constants.dbPersistenceUnit()); tree.expandItem(0); tree.setItemIcon(0, databaseIcon); Map<String, ClassMetadata> classMetadata = Db.getAllClassMetadata(); int entityId = 1; int propertyId = -1; for(Entry<String, ClassMetadata> entry : classMetadata.entrySet()) { tree.addItem(entityId); final String entity = getEntityName(entry); tree.setItemCaption(entityId, entity); tree.setParent(entityId, 0); tree.addListener((ItemClickListener) this); tree.setItemIcon(entityId, entityIcon); tree.addItem(propertyId); tree.setItemCaption(propertyId, getIdName(entry)); tree.setParent(propertyId, entityId); tree.setChildrenAllowed(propertyId, false); tree.setItemIcon(propertyId, columnIcon); propertyId--; for(String propertyName : entry.getValue().getPropertyNames()) { tree.addItem(propertyId); tree.setItemCaption(propertyId, getPropertyName(entry, propertyName)); tree.setParent(propertyId, entityId); tree.setChildrenAllowed(propertyId, false); tree.setItemIcon(propertyId, columnIcon); propertyId--; } entityId++; } queryTextArea.setSizeFull(); queryTextArea.focus(); executeQueryButton.addListener(this); clearQueryButton.addListener(this); addParamButton.addListener(this); deleteParamButton.addListener(this); executeQueryButton.setClickShortcut(KeyCode.ENTER, ModifierKey.CTRL); executeQueryButton.setDescription("Ctrl+Enter"); maxResultsTextField.setValue("100"); maxResultsTextField.setWidth("50px"); queryActionsLayout.setSpacing(true); queryActionsLayout.addComponent(executeQueryButton); queryActionsLayout.addComponent(clearQueryButton); queryActionsLayout.addComponent(maxResultsLabel); queryActionsLayout.addComponent(maxResultsTextField); queryActionsLayout.addComponent(queryLabel); queryActionsLayout.setComponentAlignment(maxResultsLabel, Alignment.BOTTOM_LEFT); queryActionsLayout.setComponentAlignment(queryLabel, Alignment.BOTTOM_LEFT); queryLayout.setSizeFull(); queryLayout.setMargin(true); queryLayout.setSpacing(true); queryLayout.addComponent(queryActionsLayout); queryLayout.addComponent(queryTextArea); queryLayout.setExpandRatio(queryTextArea, 1); paramsFieldsLayout.setSpacing(true); paramsActionsLayout.setSpacing(true); paramsActionsLayout.addComponent(addParamButton); paramsActionsLayout.addComponent(deleteParamButton); paramsActionsLayout.setComponentAlignment(addParamButton, Alignment.BOTTOM_RIGHT); paramsActionsLayout.setComponentAlignment(deleteParamButton, Alignment.BOTTOM_RIGHT); paramsLayout.setMargin(true); paramsLayout.setSpacing(true); paramsLayout.addComponent(paramsLabel); paramsLayout.addComponent(paramsFieldsLayout); paramsLayout.addComponent(paramsActionsLayout); paramsLayout.setExpandRatio(paramsFieldsLayout, 1); paramsLayout.setComponentAlignment(paramsActionsLayout, Alignment.BOTTOM_RIGHT); querySplit.setSplitPosition(60); querySplit.setFirstComponent(queryLayout); querySplit.setSecondComponent(paramsLayout); tableLayout.setSizeFull(); rightLayout.setSplitPosition(40); rightLayout.setFirstComponent(querySplit); rightLayout.setSecondComponent(tableLayout); layout.setSplitPosition(20); layout.setFirstComponent(leftLayout); layout.setSecondComponent(rightLayout); setCompositionRoot(layout); } private String getIdName(Entry<String, ClassMetadata> entry) { return entry.getValue().getIdentifierPropertyName() + " (" + entry.getValue().getIdentifierType().getReturnedClass().getSimpleName() + ")"; } private String getPropertyName(Entry<String, ClassMetadata> entry, String propertyName) { return propertyName + " (" + entry.getValue().getPropertyType(propertyName).getReturnedClass().getSimpleName() + ")"; } private String getEntityName(Entry<String, ClassMetadata> entry) { String name = null; try { name = Class.forName(entry.getValue().getEntityName()).getSimpleName(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return name; } protected void executeQuery() { try { if(queryTextArea.getValue() != null && !queryTextArea.getValue().toString().trim().isEmpty()) { Query query = Db.getCurrentSession().createQuery(queryTextArea.getValue().toString()); query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE); setQueryParams(query); if(!maxResultsTextField.getValue().toString().isEmpty()) { query.setMaxResults(new Integer(maxResultsTextField.getValue().toString())); } showResult(query.list()); } } catch(Exception e) { logger.debug("Error executing query", e); Notification.show(Constants.uiError, e.getMessage(), Notification.TYPE_ERROR_MESSAGE); } } protected void setQueryParams(Query query) { int componentCount = paramsFieldsLayout.getComponentCount(); for(int i = 0; i < componentCount; i++) { Field fieldType = paramsTypes.get(i); Field fieldValue = paramsValues.get(i); if(fieldType.getValue() == null) { throw new IllegalStateException(Constants.uiInvalidHqlParameterType); } if(fieldType.getValue().equals(BigDecimal.class)) { query.setBigDecimal(i, new BigDecimal(fieldValue.getValue().toString())); } else if(fieldType.getValue().equals(Boolean.class)) { query.setBoolean(i, new Boolean(fieldValue.getValue().toString())); } else if(fieldType.getValue().equals(Double.class)) { query.setDouble(i, new Double(fieldValue.getValue().toString())); } else if(fieldType.getValue().equals(Float.class)) { query.setFloat(i, new Float(fieldValue.getValue().toString())); } else if(fieldType.getValue().equals(Integer.class)) { query.setInteger(i, new Integer(fieldValue.getValue().toString())); } else if(fieldType.getValue().equals(Long.class)) { query.setLong(i, new Long(fieldValue.getValue().toString())); } else if(fieldType.getValue().equals(String.class)) { query.setString(i, fieldValue.getValue().toString()); } } } protected void showResult(List<?> list) { resetTable(); for(Object row : list) { addRow((Map<?, ?>) row); } } protected void addRow(Map<?, ?> row) { Object[] cells = new Object[row.size()]; int i = row.entrySet().size() - 1; for(Entry<?, ?> entry : row.entrySet()) { table.addContainerProperty(entry.getKey(), Object.class, null); cells[i] = entry.getValue(); i--; } table.addItem(cells, row); } protected void resetTable() { table = new Table(); table.setSizeFull(); table.setSelectable(true); table.addActionHandler(this); table.setColumnReorderingAllowed(true); table.setColumnCollapsingAllowed(true); tableLayout.removeAllComponents(); tableLayout.addComponent(table); } protected void addParamField() { TextField textField = new TextField(); textField.setWidth("100%"); Select select = new Select(); select.addItem(BigDecimal.class); select.addItem(Boolean.class); select.addItem(Double.class); select.addItem(Float.class); select.addItem(Integer.class); select.addItem(Long.class); select.addItem(String.class); HorizontalLayout fieldRowLayout = new HorizontalLayout(); fieldRowLayout.setWidth("100%"); fieldRowLayout.setSpacing(true); fieldRowLayout.addComponent(textField); fieldRowLayout.addComponent(select); fieldRowLayout.setExpandRatio(textField, 1); paramsFieldsLayout.addComponent(fieldRowLayout); paramsValues.add(textField); paramsTypes.add(select); } protected void deleteLastParamField() { int componentCount = paramsFieldsLayout.getComponentCount(); if(componentCount > 0) { paramsFieldsLayout.removeComponent(paramsFieldsLayout.getComponent(componentCount - 1)); paramsValues.remove(componentCount - 1); paramsTypes.remove(componentCount - 1); } } @Override public void buttonClick(ClickEvent event) { if(event.getButton().equals(executeQueryButton)) { executeQuery(); queryTextArea.focus(); } else if(event.getButton().equals(clearQueryButton)) { queryTextArea.setValue(""); queryTextArea.focus(); } else if(event.getButton().equals(addParamButton)) { addParamField(); } else if(event.getButton().equals(deleteParamButton)) { deleteLastParamField(); } } private void exportToExcel() { ExcelExport excelExport = new ExcelExport(table); excelExport.excludeCollapsedColumns(); excelExport.setDisplayTotals(false); excelExport.setReportTitle(Constants.uiHqlQuery); excelExport.setExportFileName(Constants.uiHqlQuery.toLowerCase().replace(" ", "-") + "-" + Utils.getCurrentTimeAndDate()); excelExport.export(); } @Override public void itemClick(ItemClickEvent event) { Integer itemId = (Integer) event.getItemId(); if(itemId > 0) { queryTextArea.setValue("" + queryTextArea.getValue() + tree.getItemCaption(itemId)); } else if(itemId < 0) { String property = tree.getItemCaption(itemId); property = property.substring(0, property.lastIndexOf(" (")); queryTextArea.setValue("" + queryTextArea.getValue() + property); } queryTextArea.focus(); } public Table getTable() { return table; } @Override public Action[] getActions(Object target, Object sender) { return new Action[] { ACTION_EXPORT_TO_EXCEL }; } @Override public void handleAction(Action action, Object sender, Object target) { if(action == ACTION_EXPORT_TO_EXCEL) { exportToExcel(); } } }