Java tutorial
/* * Copyright (c) 2008-2016 Haulmont. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.haulmont.cuba.gui.app.core.entitylog; import com.haulmont.bali.util.ParamsMap; import com.haulmont.chile.core.model.MetaClass; import com.haulmont.chile.core.model.MetaProperty; import com.haulmont.chile.core.model.MetaPropertyPath; import com.haulmont.chile.core.model.Range; import com.haulmont.cuba.core.app.EntityLogService; import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; import com.haulmont.cuba.core.entity.CategoryAttribute; import com.haulmont.cuba.core.entity.Entity; import com.haulmont.cuba.core.entity.HasUuid; import com.haulmont.cuba.core.global.AppBeans; import com.haulmont.cuba.core.global.Metadata; import com.haulmont.cuba.core.global.ReferenceToEntitySupport; import com.haulmont.cuba.core.global.TimeSource; import com.haulmont.cuba.gui.WindowManager; import com.haulmont.cuba.gui.WindowParams; import com.haulmont.cuba.gui.app.core.entityinspector.EntityInspectorBrowse; import com.haulmont.cuba.gui.components.*; import com.haulmont.cuba.gui.config.WindowConfig; import com.haulmont.cuba.gui.data.CollectionDatasource; import com.haulmont.cuba.gui.theme.ThemeConstants; import com.haulmont.cuba.gui.xml.layout.ComponentsFactory; import com.haulmont.cuba.security.entity.*; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.time.DateUtils; import javax.inject.Inject; import javax.inject.Named; import java.util.*; public class EntityLogBrowser extends AbstractWindow { public interface Companion { void enableTextSelection(Table table); } protected static final String SELECT_ALL_CHECK_BOX = "selectAllCheckBox"; protected static final int DEFAULT_SHOW_ROWS = 50; @Inject protected Metadata metadata; @Inject protected EntityLogService logService; @Inject protected ReferenceToEntitySupport referenceToEntitySupport; @Inject protected DynamicAttributes dynamicAttributes; @Inject protected CollectionDatasource<EntityLogItem, UUID> entityLogDs; @Inject protected CollectionDatasource<LoggedEntity, UUID> loggedEntityDs; @Inject protected CollectionDatasource<LoggedAttribute, UUID> loggedAttrDs; @Inject protected CollectionDatasource<User, UUID> usersDs; @Inject protected ComponentsFactory factory; @Inject protected LookupField entityNameField; @Inject protected LookupField filterEntityNameField; @Inject protected LookupField changeTypeField; @Inject protected CheckBox autoCheckBox; @Inject protected CheckBox manualCheckBox; @Named(SELECT_ALL_CHECK_BOX) protected CheckBox selectAllCheckBox; @Inject protected Table<LoggedEntity> loggedEntityTable; @Inject protected Table<EntityLogItem> entityLogTable; @Inject protected Table<EntityLogAttr> entityLogAttrTable; @Inject protected ScrollBoxLayout attributesBoxScroll; @Inject protected BoxLayout actionsPaneLayout; @Inject protected DateField fromDateField; @Inject protected DateField tillDateField; @Inject protected PickerField instancePicker; @Inject protected LookupField userField; @Inject protected WindowConfig config; @Inject protected ThemeConstants themeConstants; protected TextField showRowField; protected TreeMap<String, Object> entityMetaClassesMap; protected List<String> systemAttrsList; // allow or not selectAllCheckBox to change values of other checkboxes protected boolean canSelectAllCheckboxGenerateEvents = true; @Inject protected Button cancelBtn; @Override public void init(Map<String, Object> params) { WindowParams.DISABLE_AUTO_REFRESH.set(params, true); usersDs.refresh(); loggedEntityDs.refresh(); Companion companion = getCompanion(); if (companion != null) { companion.enableTextSelection(entityLogTable); companion.enableTextSelection(entityLogAttrTable); } systemAttrsList = Arrays.asList("createTs", "createdBy", "updateTs", "updatedBy", "deleteTs", "deletedBy", "version", "id"); Map<String, Object> changeTypeMap = new LinkedHashMap<>(); changeTypeMap.put(messages.getMessage(getClass(), "createField"), "C"); changeTypeMap.put(messages.getMessage(getClass(), "modifyField"), "M"); changeTypeMap.put(messages.getMessage(getClass(), "deleteField"), "D"); changeTypeMap.put(messages.getMessage(getClass(), "restoreField"), "R"); entityMetaClassesMap = getEntityMetaClasses(); entityNameField.setOptionsMap(entityMetaClassesMap); changeTypeField.setOptionsMap(changeTypeMap); filterEntityNameField.setOptionsMap(entityMetaClassesMap); Action clearAction = instancePicker.getAction("clear"); instancePicker.removeAction(clearAction); instancePicker.removeAction("lookup"); addAction(new SaveAction()); addAction(new CancelAction()); Label label1 = factory.createComponent(Label.class); label1.setValue(messages.getMessage(getClass(), "show")); label1.setAlignment(Alignment.MIDDLE_LEFT); Label label2 = factory.createComponent(Label.class); label2.setValue(messages.getMessage(getClass(), "rows")); label2.setAlignment(Alignment.MIDDLE_LEFT); ButtonsPanel panel = entityLogTable.getButtonsPanel(); showRowField = factory.createComponent(TextField.class); showRowField.setWidth(themeConstants.get("cuba.gui.EntityLogBrowser.showRowField.width")); showRowField.setValue(String.valueOf(DEFAULT_SHOW_ROWS)); panel.add(label1); panel.add(showRowField); panel.add(label2); disableControls(); setDateFieldTime(); instancePicker.setEnabled(false); PickerField.LookupAction lookupAction = new PickerField.LookupAction(instancePicker) { @Override public void actionPerform(Component component) { final MetaClass metaClass = pickerField.getMetaClass(); if (pickerField.isEditable()) { String currentWindowAlias = lookupScreen; if (currentWindowAlias == null) { if (metaClass == null) { throw new IllegalStateException("Please specify metaclass or property for PickerField"); } currentWindowAlias = windowConfig.getLookupScreenId(metaClass); } Window lookupWindow = (Window) pickerField.getFrame(); Lookup.Handler lookupWindowHandler = items -> { if (!items.isEmpty()) { Object item = items.iterator().next(); pickerField.setValue(item); afterSelect(items); } }; if (config.hasWindow(currentWindowAlias)) { lookupWindow.openLookup(currentWindowAlias, lookupWindowHandler, lookupScreenOpenType, lookupScreenParams != null ? lookupScreenParams : Collections.emptyMap()); } else { lookupWindow.openLookup(EntityInspectorBrowse.SCREEN_NAME, lookupWindowHandler, WindowManager.OpenType.THIS_TAB, ParamsMap.of("entity", metaClass.getName())); } lookupWindow.addCloseListener(actionId -> pickerField.requestFocus()); } } }; instancePicker.addAction(lookupAction); instancePicker.addAction(clearAction); entityNameField.addValueChangeListener(e -> { if (entityNameField.isEditable()) fillAttributes((String) e.getValue(), null, true); }); loggedEntityDs.addItemChangeListener(e -> { if (e.getItem() != null) { fillAttributes(e.getItem().getName(), e.getItem(), false); checkAllCheckboxes(); } else { setSelectAllCheckBox(false); clearAttributes(); } }); filterEntityNameField.addValueChangeListener(e -> { if (e.getValue() != null) { instancePicker.setEnabled(true); MetaClass metaClass = metadata.getSession().getClassNN(e.getValue().toString()); instancePicker.setMetaClass(metaClass); } else { instancePicker.setEnabled(false); } instancePicker.setValue(null); }); selectAllCheckBox.addValueChangeListener(e -> enableAllCheckBoxes((boolean) e.getValue())); entityLogTable.addGeneratedColumn("entityId", entity -> { if (entity.getObjectEntityId() != null) { return new Table.PlainTextCell(entity.getObjectEntityId().toString()); } return null; }, Table.PlainTextCell.class); } public TreeMap<String, Object> getEntityMetaClasses() { TreeMap<String, Object> options = new TreeMap<>(); for (MetaClass metaClass : metadata.getTools().getAllPersistentMetaClasses()) { if (metadata.getExtendedEntities().getExtendedClass(metaClass) == null) { MetaClass originalMetaClass = metadata.getExtendedEntities().getOriginalMetaClass(metaClass); String originalName = originalMetaClass == null ? metaClass.getName() : originalMetaClass.getName(); Class javaClass = metaClass.getJavaClass(); if (metadata.getTools().hasCompositePrimaryKey(metaClass) && !HasUuid.class.isAssignableFrom(javaClass)) { continue; } String caption = messages.getMessage(javaClass, javaClass.getSimpleName()) + " (" + metaClass.getName() + ")"; options.put(caption, originalName); } } return options; } protected void enableControls() { loggedEntityTable.setEnabled(false); entityNameField.setEditable(false); autoCheckBox.setEditable(true); manualCheckBox.setEditable(true); for (Component c : attributesBoxScroll.getComponents()) ((CheckBox) c).setEditable(true); actionsPaneLayout.setVisible(true); } protected void disableControls() { entityNameField.setEditable(false); loggedEntityTable.setEnabled(true); autoCheckBox.setEditable(false); manualCheckBox.setEditable(false); for (Component c : attributesBoxScroll.getComponents()) ((CheckBox) c).setEditable(false); actionsPaneLayout.setVisible(false); } protected void fillAttributes(String metaClassName, LoggedEntity item, boolean editable) { clearAttributes(); setSelectAllCheckBox(false); if (metaClassName != null) { MetaClass metaClass = metadata.getExtendedEntities() .getEffectiveMetaClass(metadata.getClassNN(metaClassName)); List<MetaProperty> metaProperties = new ArrayList<>(metaClass.getProperties()); selectAllCheckBox.setEditable(editable); Set<LoggedAttribute> enabledAttr = null; if (item != null) enabledAttr = item.getAttributes(); for (MetaProperty property : metaProperties) { if (allowLogProperty(property, null)) { addAttribute(enabledAttr, property, editable); } } Collection<CategoryAttribute> attributes = dynamicAttributes.getAttributesForMetaClass(metaClass); if (attributes != null) { for (CategoryAttribute categoryAttribute : attributes) { MetaPropertyPath propertyPath = DynamicAttributesUtils.getMetaPropertyPath(metaClass, categoryAttribute); MetaProperty property = propertyPath.getMetaProperty(); if (allowLogProperty(property, categoryAttribute)) { addAttribute(enabledAttr, property, editable); } } } } } protected void addAttribute(Set<LoggedAttribute> enabledAttributes, MetaProperty property, boolean editable) { CheckBox checkBox = factory.createComponent(CheckBox.class); if (enabledAttributes != null && isEntityHaveAttribute(property.getName(), enabledAttributes)) { checkBox.setValue(true); } checkBox.setId(property.getName()); checkBox.setCaption(property.getName()); checkBox.setEditable(editable); checkBox.addValueChangeListener(e -> checkAllCheckboxes()); attributesBoxScroll.add(checkBox); } protected void enableAllCheckBoxes(boolean b) { if (canSelectAllCheckboxGenerateEvents) { for (Component box : attributesBoxScroll.getComponents()) ((CheckBox) box).setValue(b); } } protected void checkAllCheckboxes() { CheckBox selectAllCheckBox = (CheckBox) attributesBoxScroll.getOwnComponent(SELECT_ALL_CHECK_BOX); if (selectAllCheckBox != null) { for (Component c : attributesBoxScroll.getComponents()) { if (!c.equals(selectAllCheckBox)) { CheckBox checkBox = (CheckBox) c; if (!checkBox.getValue()) { setSelectAllCheckBox(false); return; } } } if (attributesBoxScroll.getComponents().size() != 1) setSelectAllCheckBox(true); } } public void setSelectAllCheckBox(boolean value) { canSelectAllCheckboxGenerateEvents = false; boolean isEditable = selectAllCheckBox.isEditable(); try { selectAllCheckBox.setEditable(true); selectAllCheckBox.setValue(value); } finally { canSelectAllCheckboxGenerateEvents = true; selectAllCheckBox.setEditable(isEditable); } } public void setDateFieldTime() { TimeSource timeSource = AppBeans.get(TimeSource.NAME); Date date = timeSource.currentTimestamp(); fromDateField.setValue(DateUtils.addDays(date, -1)); tillDateField.setValue(DateUtils.addMinutes(date, 1)); } public void clearEntityLogTable() { userField.setValue(null); filterEntityNameField.setValue(null); changeTypeField.setValue(null); instancePicker.setValue(null); fromDateField.setValue(null); tillDateField.setValue(null); showRowField.setValue(String.valueOf(DEFAULT_SHOW_ROWS)); } public void search() { int maxRows; try { maxRows = Integer.parseInt(showRowField.getValue().toString()); if (maxRows >= 0) entityLogDs.setMaxResults(maxRows); else throw new NumberFormatException(); } catch (Exception e) { showNotification(messages.getMessage(getClass(), "invalidNumber"), NotificationType.HUMANIZED); return; } Entity entity = instancePicker.getValue(); Map<String, Object> params = new HashMap<>(); if (entity != null) { Object entityId = referenceToEntitySupport.getReferenceId(entity); if (entityId instanceof UUID) { params.put("entityId", entityId); } else if (entityId instanceof String) { params.put("stringEntityId", entityId); } else if (entityId instanceof Integer) { params.put("intEntityId", entityId); } else if (entityId instanceof Long) { params.put("longEntityId", entityId); } } entityLogDs.refresh(params); } public void clearAttributes() { for (Component c : attributesBoxScroll.getComponents()) if (!c.getId().equals(SELECT_ALL_CHECK_BOX)) attributesBoxScroll.remove(c); } public boolean isEntityHaveAttribute(String metaPropertyName, Set<LoggedAttribute> enabledAttr) { if ((enabledAttr != null) && !systemAttrsList.contains(metaPropertyName)) { for (LoggedAttribute logAttr : enabledAttr) if (logAttr.getName().equals(metaPropertyName)) return true; } return false; } public LoggedAttribute getLoggedAttribute(String name, Set<LoggedAttribute> enabledAttr) { for (LoggedAttribute atr : enabledAttr) if (atr.getName().equals(name)) return atr; return null; } public void create() { LoggedEntity entity = metadata.create(LoggedEntity.class); entity.setAuto(false); entity.setManual(false); setSelectAllCheckBox(false); loggedEntityDs.addItem(entity); loggedEntityTable.setEditable(true); loggedEntityTable.setSelected(entity); enableControls(); entityNameField.setEditable(true); entityNameField.requestFocus(); } public void reloadConfiguration() { logService.invalidateCache(); showNotification(getMessage("changesApplied"), NotificationType.HUMANIZED); } public void modify() { enableControls(); loggedEntityTable.setEnabled(false); cancelBtn.requestFocus(); } protected boolean allowLogProperty(MetaProperty metaProperty, CategoryAttribute categoryAttribute) { if (systemAttrsList.contains(metaProperty.getName())) { return false; } Range range = metaProperty.getRange(); if (range.isClass() && metadata.getTools().hasCompositePrimaryKey(range.asClass()) && !HasUuid.class.isAssignableFrom(range.asClass().getJavaClass())) { return false; } if (range.isClass() && range.getCardinality().isMany()) { return false; } if (categoryAttribute != null && BooleanUtils.isTrue(categoryAttribute.getIsCollection())) { return false; } return true; } protected class SaveAction extends AbstractAction { public SaveAction() { super("save"); } @Override public void actionPerform(Component component) { LoggedEntity selectedEntity = loggedEntityTable.getSelected().iterator().next(); Set<LoggedAttribute> enabledAttributes = selectedEntity.getAttributes(); for (Component c : attributesBoxScroll.getComponents()) { CheckBox currentCheckBox = (CheckBox) c; if (currentCheckBox.getId().equals(SELECT_ALL_CHECK_BOX)) continue; Boolean currentCheckBoxValue = currentCheckBox.getValue(); if (currentCheckBoxValue && !isEntityHaveAttribute(currentCheckBox.getId(), enabledAttributes)) { //add attribute if checked and not exist in table LoggedAttribute newLoggedAttribute = metadata.create(LoggedAttribute.class); newLoggedAttribute.setName(currentCheckBox.getId()); newLoggedAttribute.setEntity(selectedEntity); loggedAttrDs.addItem(newLoggedAttribute); } if (!currentCheckBoxValue && isEntityHaveAttribute(currentCheckBox.getId(), enabledAttributes)) { //remove attribute if unchecked and exist in table LoggedAttribute removeAtr = getLoggedAttribute(currentCheckBox.getId(), enabledAttributes); if (removeAtr != null) loggedAttrDs.removeItem(removeAtr); } } getDsContext().commit(); loggedEntityDs.refresh(); disableControls(); loggedEntityTable.setEnabled(true); loggedEntityTable.requestFocus(); logService.invalidateCache(); } } protected class CancelAction extends AbstractAction { public CancelAction() { super("cancel"); } @Override public void actionPerform(Component component) { loggedEntityDs.refresh(); disableControls(); loggedEntityTable.setEnabled(true); loggedEntityTable.requestFocus(); } } }