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.dynamicattributes; import com.google.common.base.Strings; import com.haulmont.bali.util.ParamsMap; import com.haulmont.bali.util.Preconditions; import com.haulmont.chile.core.model.MetaClass; import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributes; import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils; import com.haulmont.cuba.core.entity.BaseGenericIdEntity; import com.haulmont.cuba.core.entity.Categorized; import com.haulmont.cuba.core.entity.CategoryAttribute; import com.haulmont.cuba.core.entity.Entity; import com.haulmont.cuba.core.global.*; import com.haulmont.cuba.gui.WindowManager.OpenType; import com.haulmont.cuba.gui.WindowParams; import com.haulmont.cuba.gui.commonlookup.CommonLookupController; import com.haulmont.cuba.gui.components.PickerField; import com.haulmont.cuba.gui.config.WindowConfig; import com.haulmont.cuba.gui.data.CollectionDatasource; import com.haulmont.cuba.gui.data.Datasource; import com.haulmont.cuba.gui.data.DsBuilder; import com.haulmont.cuba.gui.data.impl.DatasourceImplementation; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import javax.annotation.Nullable; import javax.inject.Inject; import java.util.*; import java.util.stream.Collectors; import static java.lang.String.format; @Component(DynamicAttributesGuiTools.NAME) public class DynamicAttributesGuiTools { public static final String NAME = "cuba_DynamicAttributesGuiTools"; @Inject protected DynamicAttributes dynamicAttributes; @Inject protected WindowConfig windowConfig; @Inject protected Metadata metadata; @Inject protected ReferenceToEntitySupport referenceToEntitySupport; @Inject protected DataManager dataManager; /** * Enforce the datasource to change modified status if dynamic attribute is changed */ @SuppressWarnings("unchecked") public void listenDynamicAttributesChanges(final Datasource datasource) { if (datasource != null && datasource.getLoadDynamicAttributes()) { datasource.addItemPropertyChangeListener(e -> { if (DynamicAttributesUtils.isDynamicAttribute(e.getProperty())) { ((DatasourceImplementation) datasource).modified(e.getItem()); } }); } } /** * Get attributes which should be added automatically to the screen and component. * Based on visibility settings from category attribute editor. */ public Set<CategoryAttribute> getAttributesToShowOnTheScreen(MetaClass metaClass, String screen, @Nullable String component) { Collection<CategoryAttribute> attributesForMetaClass = dynamicAttributes .getAttributesForMetaClass(metaClass); Set<CategoryAttribute> categoryAttributes = new LinkedHashSet<>(); for (CategoryAttribute attribute : attributesForMetaClass) { if (attributeShouldBeShownOnTheScreen(screen, component, attribute)) { categoryAttributes.add(attribute); } } return categoryAttributes; } /** * Method checks whether any class in the view hierarchy contains dynamic attributes that must be displayed on * the current screen */ public boolean screenContainsDynamicAttributes(View mainDatasourceView, String screenId) { DynamicAttributesGuiTools dynamicAttributesGuiTools = AppBeans.get(DynamicAttributesGuiTools.class); Set<Class> classesWithDynamicAttributes = collectEntityClassesWithDynamicAttributes(mainDatasourceView); for (Class classWithDynamicAttributes : classesWithDynamicAttributes) { MetaClass metaClass = metadata.getClassNN(classWithDynamicAttributes); if (!dynamicAttributesGuiTools.getAttributesToShowOnTheScreen(metaClass, screenId, null).isEmpty()) { return true; } } return false; } protected Set<Class> collectEntityClassesWithDynamicAttributes(@Nullable View view) { if (view == null) { return Collections.emptySet(); } DynamicAttributes dynamicAttributes = AppBeans.get(DynamicAttributes.class); Metadata metadata = AppBeans.get(Metadata.class); return collectEntityClasses(view, new HashSet<>()).stream() .filter(BaseGenericIdEntity.class::isAssignableFrom).filter(aClass -> !dynamicAttributes .getAttributesForMetaClass(metadata.getClassNN(aClass)).isEmpty()) .collect(Collectors.toSet()); } protected Set<Class> collectEntityClasses(View view, Set<View> visited) { if (visited.contains(view)) { return Collections.emptySet(); } else { visited.add(view); } HashSet<Class> classes = new HashSet<>(); classes.add(view.getEntityClass()); for (ViewProperty viewProperty : view.getProperties()) { if (viewProperty.getView() != null) { classes.addAll(collectEntityClasses(viewProperty.getView(), visited)); } } return classes; } public void initDefaultAttributeValues(BaseGenericIdEntity item, MetaClass metaClass) { Preconditions.checkNotNullArgument(metaClass, "metaClass is null"); Collection<CategoryAttribute> attributes = dynamicAttributes.getAttributesForMetaClass(metaClass); if (item.getDynamicAttributes() == null) { item.setDynamicAttributes(new HashMap<>()); } Date currentTimestamp = AppBeans.get(TimeSource.NAME, TimeSource.class).currentTimestamp(); boolean entityIsCategorized = item instanceof Categorized && ((Categorized) item).getCategory() != null; for (CategoryAttribute categoryAttribute : attributes) { String code = DynamicAttributesUtils.encodeAttributeCode(categoryAttribute.getCode()); if (entityIsCategorized && !categoryAttribute.getCategory().equals(((Categorized) item).getCategory())) { item.setValue(code, null);//cleanup attributes from not dedicated category continue; } if (item.getValue(code) != null) { continue;//skip not null attributes } if (categoryAttribute.getDefaultValue() != null) { if (BooleanUtils.isTrue(categoryAttribute.getIsEntity())) { MetaClass entityMetaClass = metadata.getClassNN(categoryAttribute.getJavaClassForEntity()); LoadContext<Entity> lc = new LoadContext<>(entityMetaClass).setView(View.MINIMAL); String pkName = referenceToEntitySupport.getPrimaryKeyForLoadingEntity(entityMetaClass); lc.setQueryString( format("select e from %s e where e.%s = :entityId", entityMetaClass.getName(), pkName)) .setParameter("entityId", categoryAttribute.getDefaultValue()); Entity defaultEntity = dataManager.load(lc); item.setValue(code, defaultEntity); } else { item.setValue(code, categoryAttribute.getDefaultValue()); } } else if (Boolean.TRUE.equals(categoryAttribute.getDefaultDateIsCurrent())) { item.setValue(code, currentTimestamp); } } } @SuppressWarnings("unchecked") public void listenCategoryChanges(Datasource ds) { ds.addItemPropertyChangeListener(e -> { if ("category".equals(e.getProperty())) { initDefaultAttributeValues((BaseGenericIdEntity) e.getItem(), e.getItem().getMetaClass()); } }); } protected boolean attributeShouldBeShownOnTheScreen(String screen, String component, CategoryAttribute attribute) { Set<String> targetScreensSet = attribute.targetScreensSet(); return targetScreensSet.contains(screen) || targetScreensSet.contains(screen + "#" + component); } /** * Initializes the pickerField for selecting the dynamic attribute value. If the CategoryAttribute has "where" or * "join" clauses then the data in lookup screens will be filtered with these clauses * * @param pickerField PickerField component whose lookup action must be initialized * @param categoryAttribute CategoryAttribute that is represented by the pickerField */ public void initEntityPickerField(PickerField pickerField, CategoryAttribute categoryAttribute) { Class javaClass = categoryAttribute.getJavaClassForEntity(); if (javaClass == null) { throw new IllegalArgumentException("Entity type is not specified in category attribute"); } MetaClass metaClass = metadata.getClassNN(javaClass); PickerField.LookupAction lookupAction = (PickerField.LookupAction) pickerField .getAction(PickerField.LookupAction.NAME); if (!Strings.isNullOrEmpty(categoryAttribute.getJoinClause()) || !Strings.isNullOrEmpty(categoryAttribute.getWhereClause())) { lookupAction = createLookupAction(pickerField, categoryAttribute.getJoinClause(), categoryAttribute.getWhereClause()); pickerField.addAction(lookupAction); } if (lookupAction == null) { lookupAction = pickerField.addLookupAction(); } String screen = categoryAttribute.getScreen(); if (StringUtils.isNotBlank(screen)) { lookupAction.setLookupScreen(screen); } else { screen = windowConfig.getBrowseScreenId(metaClass); if (windowConfig.findWindowInfo(screen) != null) { lookupAction.setLookupScreen(screen); lookupAction.setLookupScreenOpenType(OpenType.THIS_TAB); } else { lookupAction.setLookupScreen(CommonLookupController.SCREEN_ID); lookupAction.setLookupScreenParams(ParamsMap.of(CommonLookupController.CLASS_PARAMETER, metaClass)); lookupAction.setLookupScreenOpenType(OpenType.DIALOG); } } } /** * Creates the collection datasource that is used for selecting the dynamic attribute value. If the * CategoryAttribute has "where" or "join" clauses then only items that satisfy these clauses will be presented in * the options datasource */ public CollectionDatasource createOptionsDatasourceForLookup(MetaClass metaClass, String joinClause, String whereClause) { CollectionDatasource optionsDatasource = DsBuilder.create().setMetaClass(metaClass) .setViewName(View.MINIMAL).buildCollectionDatasource(); String query = "select e from " + metaClass.getName() + " e"; if (!Strings.isNullOrEmpty(joinClause)) { query += " " + joinClause; } if (!Strings.isNullOrEmpty(whereClause)) { query += " where " + whereClause.replaceAll("\\{E\\}", "e"); } optionsDatasource.setQuery(query); optionsDatasource.refresh(); return optionsDatasource; } /** * Creates the lookup action that will open the lookup screen with the dynamic filter applied. This filter contains * a condition with join and where clauses */ public PickerField.LookupAction createLookupAction(PickerField pickerField, String joinClause, String whereClause) { FilteringLookupAction filteringLookupAction = new FilteringLookupAction(pickerField, joinClause, whereClause); Map<String, Object> params = new HashMap<>(); WindowParams.DISABLE_RESUME_SUSPENDED.set(params, true); WindowParams.DISABLE_AUTO_REFRESH.set(params, true); filteringLookupAction.setLookupScreenParams(params); return filteringLookupAction; } }