Java tutorial
//Copyright (C) 2010 Novabit Informationssysteme GmbH // //This file is part of Nuclos. // //Nuclos is free software: you can redistribute it and/or modify //it under the terms of the GNU Affero General Public License as published by //the Free Software Foundation, either version 3 of the License, or //(at your option) any later version. // //Nuclos 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 Affero General Public License for more details. // //You should have received a copy of the GNU Affero General Public License //along with Nuclos. If not, see <http://www.gnu.org/licenses/>. package org.nuclos.server.genericobject.ejb3; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.security.RolesAllowed; import org.apache.commons.lang.NullArgumentException; import org.apache.log4j.Logger; import org.nuclos.api.eventsupport.DeleteFinalSupport; import org.nuclos.api.eventsupport.DeleteSupport; import org.nuclos.api.eventsupport.InsertFinalSupport; import org.nuclos.api.eventsupport.InsertSupport; import org.nuclos.api.eventsupport.UpdateFinalSupport; import org.nuclos.api.eventsupport.UpdateSupport; import org.nuclos.common.GenericObjectMetaDataVO; import org.nuclos.common.NuclosBusinessException; import org.nuclos.common.NuclosEOField; import org.nuclos.common.NuclosEntity; import org.nuclos.common.NuclosFatalException; import org.nuclos.common.ParameterProvider; import org.nuclos.common.SearchConditionUtils; import org.nuclos.common.UsageCriteria; import org.nuclos.common.attribute.DynamicAttributeVO; import org.nuclos.common.collect.collectable.searchcondition.CollectableIsNullCondition; import org.nuclos.common.collect.collectable.searchcondition.CollectableSearchCondition; import org.nuclos.common.collection.CollectionUtils; import org.nuclos.common.collection.MasterDataToEntityObjectTransformer; import org.nuclos.common.dal.DalCallResult; import org.nuclos.common.dal.DalSupportForMD; import org.nuclos.common.dal.vo.EOGenericObjectVO; import org.nuclos.common.dal.vo.EntityMetaDataVO; import org.nuclos.common.dal.vo.EntityObjectVO; import org.nuclos.common.dal.vo.SystemFields; import org.nuclos.common.entityobject.CollectableEOEntityField; import org.nuclos.common.security.Permission; import org.nuclos.common2.EntityAndFieldName; import org.nuclos.common2.IdUtils; import org.nuclos.common2.InternalTimestamp; import org.nuclos.common2.LangUtils; import org.nuclos.common2.ServiceLocator; import org.nuclos.common2.StringUtils; import org.nuclos.common2.TruncatableCollection; import org.nuclos.common2.TruncatableCollectionDecorator; import org.nuclos.common2.exception.CommonBusinessException; import org.nuclos.common2.exception.CommonCreateException; import org.nuclos.common2.exception.CommonFatalException; import org.nuclos.common2.exception.CommonFinderException; import org.nuclos.common2.exception.CommonPermissionException; import org.nuclos.common2.exception.CommonRemoveException; import org.nuclos.common2.exception.CommonStaleVersionException; import org.nuclos.common2.exception.CommonValidationException; import org.nuclos.server.attribute.BadAttributeValueException; import org.nuclos.server.attribute.ejb3.LayoutFacadeLocal; import org.nuclos.server.attribute.valueobject.AttributeCVO; import org.nuclos.server.common.AttributeCache; import org.nuclos.server.common.BusinessIDFactory; import org.nuclos.server.common.MasterDataMetaCache; import org.nuclos.server.common.MetaDataServerProvider; import org.nuclos.server.common.ModuleConstants; import org.nuclos.server.common.SecurityCache; import org.nuclos.server.common.ServerParameterProvider; import org.nuclos.server.common.ServerServiceLocator; import org.nuclos.server.common.ejb3.NuclosFacadeBean; import org.nuclos.server.common.valueobject.NuclosValueObject; import org.nuclos.server.dal.DalSupportForGO; import org.nuclos.server.dal.DalUtils; import org.nuclos.server.dal.provider.NucletDalProvider; import org.nuclos.server.dblayer.DbException; import org.nuclos.server.dblayer.DbInvalidResultSizeException; import org.nuclos.server.dblayer.DbStatementUtils; import org.nuclos.server.dblayer.DbTuple; import org.nuclos.server.dblayer.query.DbColumnExpression; import org.nuclos.server.dblayer.query.DbCondition; import org.nuclos.server.dblayer.query.DbFrom; import org.nuclos.server.dblayer.query.DbQuery; import org.nuclos.server.dblayer.query.DbQueryBuilder; import org.nuclos.server.dblayer.query.DbSelection; import org.nuclos.server.eventsupport.ejb3.EventSupportFacadeLocal; import org.nuclos.server.genericobject.GenericObjectMetaDataCache; import org.nuclos.server.genericobject.GenericObjectProxyList; import org.nuclos.server.genericobject.Modules; import org.nuclos.server.genericobject.ProxyList; import org.nuclos.server.genericobject.searchcondition.CollectableSearchExpression; import org.nuclos.server.genericobject.valueobject.GenericObjectRelationVO; import org.nuclos.server.genericobject.valueobject.GenericObjectVO; import org.nuclos.server.genericobject.valueobject.GenericObjectWithDependantsVO; import org.nuclos.server.genericobject.valueobject.LogbookVO; import org.nuclos.server.masterdata.MasterDataWrapper; import org.nuclos.server.masterdata.ejb3.MasterDataFacadeHelper; import org.nuclos.server.masterdata.ejb3.MasterDataFacadeLocal; import org.nuclos.server.masterdata.valueobject.DependantMasterDataMap; import org.nuclos.server.masterdata.valueobject.DependantMasterDataMapImpl; import org.nuclos.server.masterdata.valueobject.DependantWrapper; import org.nuclos.server.masterdata.valueobject.MasterDataMetaVO; import org.nuclos.server.masterdata.valueobject.MasterDataVO; import org.nuclos.server.navigation.treenode.GenericObjectTreeNode; import org.nuclos.server.navigation.treenode.GenericObjectTreeNode.RelationDirection; import org.nuclos.server.ruleengine.NuclosBusinessRuleException; import org.nuclos.server.ruleengine.ejb3.RuleEngineFacadeLocal; import org.nuclos.server.ruleengine.valueobject.RuleEventUsageVO; import org.nuclos.server.ruleengine.valueobject.RuleObjectContainerCVO; import org.nuclos.server.ruleengine.valueobject.RuleObjectContainerCVOImpl; import org.nuclos.server.ruleengine.valueobject.RuleObjectContainerCVOImpl.Event; import org.nuclos.server.ruleengine.valueobject.RuleVO; import org.nuclos.server.statemodel.NuclosNoAdequateStatemodelException; import org.nuclos.server.statemodel.NuclosSubsequentStateNotLegalException; import org.nuclos.server.statemodel.ejb3.StateFacadeLocal; import org.nuclos.server.statemodel.valueobject.StateHistoryVO; import org.nuclos.server.validation.ValidationSupport; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; /** * Facade bean for all generic object management functions. * <br> * <br>Created by Novabit Informationssysteme GmbH * <br>Please visit <a href="http://www.novabit.de">www.novabit.de</a> */ @Transactional(noRollbackFor = { Exception.class }) public class GenericObjectFacadeBean extends NuclosFacadeBean implements GenericObjectFacadeRemote { private static final Logger LOG = Logger.getLogger(GenericObjectFacadeBean.class); // private GenericObjectFacadeHelper helper; private MasterDataFacadeLocal masterDataFacade; private AttributeCache attributeCache; private ValidationSupport validationSupport; /** * @deprecated */ private MasterDataFacadeHelper masterDataFacadeHelper; public GenericObjectFacadeBean() { } @Autowired void setMasterDataFacadeHelper(MasterDataFacadeHelper masterDataFacadeHelper) { this.masterDataFacadeHelper = masterDataFacadeHelper; } @Autowired void setGenericObjectFacadeHelper(GenericObjectFacadeHelper genericObjectFacadeHelper) { this.helper = genericObjectFacadeHelper; } @Autowired public void setValidationSupport(ValidationSupport validationSupport) { this.validationSupport = validationSupport; } private AttributeCache getAttributeCache() { if (attributeCache == null) { attributeCache = AttributeCache.getInstance(); } return attributeCache; } private final MasterDataFacadeLocal getMasterDataFacade() { if (masterDataFacade == null) { masterDataFacade = ServerServiceLocator.getInstance().getFacade(MasterDataFacadeLocal.class); } return masterDataFacade; } @RolesAllowed("Login") public GenericObjectMetaDataVO getMetaData() { return GenericObjectMetaDataCache.getInstance().getMetaDataCVO(); } @RolesAllowed("Login") public Map<Integer, String> getResourceMap() { return GenericObjectMetaDataCache.getInstance().getResourceMap(); } /** * @param iGenericObjectId * @return the generic object with the given id * @postcondition result != null * @throws CommonFinderException if there is no object with the given id. * @throws CommonPermissionException if the user doesn't have the permission to view the generic object with the given id. * @nucleus.permission mayRead(module) */ @RolesAllowed("Login") public GenericObjectVO get(Integer iGenericObjectId) throws CommonFinderException, CommonPermissionException { return get(iGenericObjectId, true); } /** * @param iGenericObjectId * @param bCheckPermission * @return the generic object with the given id * @postcondition result != null * @throws CommonFinderException if there is no object with the given id. * @throws CommonPermissionException if the user doesn't have the permission to view the generic object with the given id. * @nucleus.permission mayRead(module) */ @RolesAllowed("Login") public GenericObjectVO get(Integer iGenericObjectId, boolean bCheckPermission) throws CommonFinderException, CommonPermissionException { // GenericObjectVO govo = MasterDataWrapper.getGenericObjectVO(getMasterDataFacade().get(ENTITY_NAME_GENERICOBJECT, iGenericObjectId)); // govo = helper.getValueObject(govo); final GenericObjectVO govo; try { govo = DalSupportForGO.getGenericObject(iGenericObjectId); } catch (Exception e) { throw new CommonFinderException(); } if (bCheckPermission) { checkReadAllowedForModule(govo.getModuleId(), iGenericObjectId); getRecordGrantUtils().checkInternal(MetaDataServerProvider.getInstance() .getEntity(IdUtils.toLongId(govo.getModuleId())).getEntity(), IdUtils.toLongId(iGenericObjectId)); } assert govo != null; return govo; } private void checkForStaleVersion(GenericObjectVO oldGO, GenericObjectVO newGO) throws CommonStaleVersionException { if (oldGO.getVersion() != newGO.getVersion()) { throw new CommonStaleVersionException("generic object", newGO.toDescription(), oldGO.toDescription()); } } /** * @param iGenericObjectId * @param stRequiredSubEntityNames the dependant objects with the subentites with the given names will be fetched. Null means all. * @return the complete generic object with the given id, along with its required dependants. * @throws CommonFinderException if no such object was found. * @throws CommonPermissionException if the user doesn't have the permission to view the generic object. * @throws IllegalArgumentException if the given module id doesn't match the generic object's module id. * @postcondition result != null * @postcondition result.isComplete() */ @RolesAllowed("Login") public GenericObjectWithDependantsVO getWithDependants(Integer iGenericObjectId, Set<String> stRequiredSubEntityNames) throws CommonPermissionException, CommonFinderException { return this.getWithDependants(iGenericObjectId, stRequiredSubEntityNames, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public GenericObjectWithDependantsVO getWithDependants(Integer iGenericObjectId, Set<String> stRequiredSubEntityNames, String customUsage) throws CommonPermissionException, CommonFinderException { final GenericObjectWithDependantsVO result = new GenericObjectWithDependantsVO(this.get(iGenericObjectId), new DependantMasterDataMapImpl()); final Set<String> stSubEntityNames; if (stRequiredSubEntityNames == null) { final GenericObjectMetaDataCache lometadataprovider = GenericObjectMetaDataCache.getInstance(); stSubEntityNames = lometadataprovider.getSubFormEntityNamesByLayoutId(lometadataprovider .getBestMatchingLayoutId(result.getUsageCriteria(lometadataprovider, customUsage), false)); } else { stSubEntityNames = stRequiredSubEntityNames; } _fillDependants(result, result.getUsageCriteria(getAttributeCache(), customUsage), stSubEntityNames, customUsage); assert result != null; assert result.isComplete(); return result; } /** * @param iGenericObjectId * @return the version of the given genericobject id. * @throws CommonPermissionException * @throws CommonFinderException */ @RolesAllowed("Login") public Integer getVersion(int iGenericObjectId) throws CommonFinderException, CommonPermissionException { return this.get(iGenericObjectId).getVersion(); } /** * @param gowdvo * @param mpDependants * @param bAll * @return reload the dependant data of the genericobject, if bAll is false, only the direct * dependants (highest hierarchie of subforms) will be reloaded * @throws CommonFinderException if no such object was found. */ @RolesAllowed("Login") public DependantMasterDataMap reloadDependants(GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean bAll, String customUsage) throws CommonFinderException { LayoutFacadeLocal layoutFacade = ServerServiceLocator.getInstance().getFacade(LayoutFacadeLocal.class); final Map<EntityAndFieldName, String> collSubEntities = layoutFacade .getSubFormEntityAndParentSubFormEntityNames( Modules.getInstance().getEntityNameByModuleId(govo.getModuleId()), govo.getId(), false, customUsage); if (mpDependants == null) { mpDependants = new DependantMasterDataMapImpl(); } for (EntityAndFieldName eafn : collSubEntities.keySet()) { // care only about dependant data which are on the highest level if (collSubEntities.get(eafn) == null) { final String entity = eafn.getEntityName(); EntityMetaDataVO eMeta = MetaDataServerProvider.getInstance().getEntity(entity); if (!eMeta.isEditable()) { continue; } final String sForeignKeyFieldName = LangUtils.defaultIfNull(eafn.getFieldName(), ModuleConstants.DEFAULT_FOREIGNKEYFIELDNAME); Collection<MasterDataVO> collmdVO = getMasterDataFacade().getDependantMasterData(entity, sForeignKeyFieldName, govo.getId()); mpDependants.setData(entity, CollectionUtils.transform(collmdVO, new MasterDataToEntityObjectTransformer(entity))); if (bAll) { for (MasterDataVO mdVO : collmdVO) { // now read all dependant data of the child subforms getMasterDataFacade().readAllDependants(entity, mdVO.getIntId(), mdVO.getDependants(), mdVO.isRemoved(), entity, collSubEntities); } } } } return mpDependants; } /** * gets generic object vo for a given generic object id, along with its dependants. * @param iGenericObjectId id of generic object * @return generic object vo with dependants * @throws CommonFinderException if no such object was found. * deprecated merge with getWithDependants? * @nucleus.permission mayRead(module) */ @RolesAllowed("Login") public RuleObjectContainerCVO getRuleObjectContainerCVO(Event event, Integer iGenericObjectId, String customUsage) throws CommonPermissionException, CommonFinderException { // @todo merge with getWithDependants? final GenericObjectVO govo = this.get(iGenericObjectId); return new RuleObjectContainerCVOImpl(event, govo, reloadDependants(govo, null, true, customUsage)); } /** * gets generic object with dependants vo for a given generic object id (historical, readonly view) * @param iGenericObjectId id of generic object to show historical information for * @param dateHistorical date to show historical information for * @return generic object with dependants vo at the given point in time * @throws CommonFinderException if the given object didn't exist at the given point in time. * @precondition dateHistorical != null * @postcondition result != null * @nucleus.permission mayRead(module) */ @RolesAllowed("Login") public GenericObjectWithDependantsVO getHistorical(int iGenericObjectId, Date dateHistorical, String customUsage) throws CommonFinderException, CommonPermissionException { debug("Entering getHistorical(Integer iGenericObjectId, Date dateHistorical)"); if (dateHistorical == null) { throw new NullArgumentException("dateHistorical"); } final RuleObjectContainerCVO loccvo = this.getRuleObjectContainerCVO(Event.UNDEFINED, iGenericObjectId, customUsage); final GenericObjectVO govoResult = loccvo.getGenericObject(); final DependantMasterDataMap mpDependantsResult = loccvo.getDependants(); final Calendar calendar = new GregorianCalendar(); calendar.setTime(dateHistorical); // If dateHistorical has no time components, we can assume that the user wants to see the state of the object at the end of that day. if (calendar.get(Calendar.HOUR_OF_DAY) + calendar.get(Calendar.MINUTE) + calendar.get(Calendar.SECOND) == 0) { calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 59); calendar.set(Calendar.SECOND, 0); } dateHistorical = calendar.getTime(); // Check if the object existed at the historical date: final Date dateCreatedAt = govoResult.getCreatedAt(); if (dateHistorical.before(dateCreatedAt)) { throw new CommonFinderException("genericobject.facade.exception.1");//"Das Objekt existierte zum angegebenen Zeitpunkt nicht."); } debug("Historical Date we want to see : " + dateHistorical.toString()); debug("Date of creation of record : " + dateCreatedAt.toString()); govoResult.setAttributes(GenericObjectFacadeHelper .getHistoricalAttributes(govoResult, dateHistorical, mpDependantsResult).values()); this.debug("Leaving getHistorical(Integer iGenericObjectId, Date dateHistorical)"); assert govoResult != null; return new GenericObjectWithDependantsVO(govoResult, mpDependantsResult); } /** * gets all generic objects that match a given search condition * @param iModuleId id of module to search for generic objects in * @param clctexpr * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @return list of generic object value objects - without dependants and parent objects! * @todo restrict permission - check module id! * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public List<GenericObjectWithDependantsVO> getGenericObjects(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds) { return this.getGenericObjects(iModuleId, clctexpr, stRequiredAttributeIds, Collections.<String>emptySet(), ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public List<GenericObjectWithDependantsVO> getGenericObjects(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, String customUsage) { return this.getGenericObjects(iModuleId, clctexpr, stRequiredAttributeIds, Collections.<String>emptySet(), customUsage); } /** * gets all generic objects that match a given search condition * @param iModuleId id of module to search for generic objects in * @param clctexpr * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @param stRequiredSubEntityNames * @return list of generic object value objects with specified dependants and without parent objects! * @postcondition result != null * @Deprecated use with customUsage */ @Deprecated public List<GenericObjectWithDependantsVO> getGenericObjects(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames) { return helper.getGenericObjects(iModuleId, clctexpr, stRequiredSubEntityNames, this.getCurrentUserName(), ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } public List<GenericObjectWithDependantsVO> getGenericObjects(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, String customUsage) { return helper.getGenericObjects(iModuleId, clctexpr, stRequiredSubEntityNames, this.getCurrentUserName(), customUsage); } /** * gets all generic objects that match a given search condition * @param iModuleId id of module to search for generic objects in * @param clctexpr * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @param stRequiredSubEntityNames * @return list of generic object value objects with specified dependants and without parent objects! * @postcondition result != null * @Deprecated use with customUsage */ @Deprecated public List<GenericObjectWithDependantsVO> getGenericObjects(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, boolean bIncludeParentObjects) { return getGenericObjects(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } public List<GenericObjectWithDependantsVO> getGenericObjects(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, String customUsage, boolean bIncludeParentObjects) { return getGenericObjects(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, customUsage); } /** * gets all generic objects along with its dependants, that match a given search condition * @param iModuleId id of module to search for generic objects in * @param clctexpr value object containing search expression * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @param stRequiredSubEntityNames * @param bIncludeParentObjects * @param bIncludeSubModules Include submodules in search? * @return list of generic object value objects * @precondition stRequiredSubEntityNames != null * @todo rename to getGenericObjectProxyList? * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public ProxyList<GenericObjectWithDependantsVO> getGenericObjectsWithDependants(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, boolean bIncludeParentObjects, boolean bIncludeSubModules) { return new GenericObjectProxyList(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, bIncludeParentObjects, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public ProxyList<GenericObjectWithDependantsVO> getGenericObjectsWithDependants(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, boolean bIncludeParentObjects, boolean bIncludeSubModules, String customUsage) { return new GenericObjectProxyList(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, bIncludeParentObjects, customUsage); } /** * gets all generic objects along with its dependants, that match a given search condition, but * clears the values of all attributes on which the current user has no read permission * NOTE: use only within report mechanism * @param iModuleId id of module to search for generic objects in * @param clctexpr value object containing search expression * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @param stRequiredSubEntityNames * @param bIncludeParentObjects * @param bIncludeSubModules Include submodules in search? * @return list of generic object value objects * @precondition stRequiredSubEntityNames != null * @todo rename to getGenericObjectProxyList? * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public ProxyList<GenericObjectWithDependantsVO> getPrintableGenericObjectsWithDependants(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, boolean bIncludeParentObjects, boolean bIncludeSubModules) { return getPrintableGenericObjectsWithDependants(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, bIncludeParentObjects, bIncludeSubModules, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public ProxyList<GenericObjectWithDependantsVO> getPrintableGenericObjectsWithDependants(Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, boolean bIncludeParentObjects, boolean bIncludeSubModules, String customUsage) { stRequiredAttributeIds.add(NuclosEOField.STATENUMBER.getMetaData().getId().intValue()); stRequiredAttributeIds.add(NuclosEOField.STATE.getMetaData().getId().intValue()); //stRequiredAttributeIds.add(NuclosEOField.STATEICON.getMetaData().getId().intValue()); ProxyList<GenericObjectWithDependantsVO> proxyList = this.getGenericObjectsWithDependants(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, bIncludeParentObjects, bIncludeSubModules, customUsage); // remove all attribute and subform values on which the current user has no read permission for (GenericObjectWithDependantsVO gowdvo : proxyList) { Integer iStatus = gowdvo.getAttribute(NuclosEOField.STATE.getMetaData().getField(), getAttributeCache()) .getValueId(); if (iStatus != null) { for (DynamicAttributeVO dynamicAttributeVO : gowdvo.getAttributes()) { String sAtributeName = getAttributeCache().getAttribute(dynamicAttributeVO.getAttributeId()) .getName(); if (SecurityCache.getInstance().getAttributePermission( Modules.getInstance().getEntityNameByModuleId(gowdvo.getModuleId()), sAtributeName, iStatus) == null) { dynamicAttributeVO.setValue(null); } } DependantMasterDataMap dependants = gowdvo.getDependants(); for (String entity : dependants.getEntityNames()) { Map<Integer, Permission> permission = SecurityCache.getInstance() .getSubForm(getCurrentUserName(), entity); if (permission.get(iStatus) == null) { for (EntityObjectVO mdvo : dependants.getData(entity)) { mdvo.getFields().clear(); mdvo.getFieldIds().clear(); } } } } } return proxyList; } /** * gets all generic objects that match a given search condition * @param iModuleId id of module to search for generic objects in * @param clctexpr * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @param stRequiredSubEntityNames * @param iMaxRowCount the maximum number of rows * @return list of generic object value objects * @precondition stRequiredSubEntityNames != null * @precondition iMaxRowCount > 0 * @postcondition result.size() <= iMaxRowCount * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public TruncatableCollection<GenericObjectWithDependantsVO> getRestrictedNumberOfGenericObjects( Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, int iMaxRowCount) { return getRestrictedNumberOfGenericObjects(iModuleId, clctexpr, stRequiredAttributeIds, stRequiredSubEntityNames, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY), iMaxRowCount); } @RolesAllowed("Login") @Deprecated public TruncatableCollection<GenericObjectWithDependantsVO> getRestrictedNumberOfGenericObjects( Integer iModuleId, CollectableSearchExpression clctexpr, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, String customUsage, int iMaxRowCount) { if (iMaxRowCount <= 0) { throw new IllegalArgumentException("iMaxRowCount == " + iMaxRowCount); } final EntityMetaDataVO eMeta = MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)); final List<GenericObjectWithDependantsVO> lstResult = new ArrayList<GenericObjectWithDependantsVO>( Math.min(iMaxRowCount + 1, 1000)); for (EntityObjectVO eo : NucletDalProvider.getInstance().getEntityObjectProcessor(eMeta.getEntity()) .getBySearchExpression(appendRecordGrants(clctexpr, eMeta), iMaxRowCount + 1, true)) { final GenericObjectWithDependantsVO go = new GenericObjectWithDependantsVO( DalSupportForGO.getGenericObjectVO(eo), new DependantMasterDataMapImpl()); try { if (!stRequiredSubEntityNames.isEmpty()) _fillDependants(go, go.getUsageCriteria(getAttributeCache(), customUsage), stRequiredSubEntityNames, customUsage); } catch (CommonFinderException e) { throw new NuclosFatalException(e); } lstResult.add(go); } assert lstResult.size() <= iMaxRowCount + 1; final boolean bTruncated = (lstResult.size() == iMaxRowCount + 1); if (bTruncated) { // remove the last entry: lstResult.remove(iMaxRowCount); assert lstResult.size() == iMaxRowCount; } final int iTotalRowCount = bTruncated ? NucletDalProvider.getInstance().getEntityObjectProcessor(eMeta.getEntity()).count(clctexpr) : lstResult.size(); final TruncatableCollection<GenericObjectWithDependantsVO> result = new TruncatableCollectionDecorator<GenericObjectWithDependantsVO>( lstResult, bTruncated, iTotalRowCount); assert result.size() <= iMaxRowCount; return result; } /** * gets the ids of all leased objects that match a given search expression (ordered, when necessary) * @param iModuleId id of module to search for leased objects in * @param cond condition that the leased objects to be found must satisfy * @return List<Integer> list of leased object ids */ public List<Integer> getGenericObjectIds(Integer iModuleId, CollectableSearchExpression cse) { EntityMetaDataVO eMeta = MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)); List<Long> ids = NucletDalProvider.getInstance().getEntityObjectProcessor(eMeta.getEntity()) .getIdsBySearchExprUserGroups(appendRecordGrants(cse, eMeta.getEntity()), IdUtils.toLongId(iModuleId), getCurrentUserName()); return DalUtils.convertLongIdList(ids); } /** * gets the ids of all generic objects that match a given search condition * @param iModuleId id of module to search for generic objects in * @param cond condition that the generic objects to be found must satisfy * @return List<Integer> list of generic object ids */ public List<Integer> getGenericObjectIds(Integer iModuleId, CollectableSearchCondition cond) { return this.getGenericObjectIds(iModuleId, new CollectableSearchExpression(cond)); } /** * gets more leased objects that match a given search condition * @param iModuleId id of module to search for leased objects in * @param clctexpr value object containing search condition * @param lstSortOrderValues field values for building correct where clause * @param iRecordCount number of records to get for search condition * @param stRequiredAttributeIds may be <code>null</code>, which means all attributes are required * @param stRequiredSubEntityNames * @param bIncludeParentObjects * @return list of leased object value objects * @precondition stRequiredSubEntityNames != null * @Deprecated use with customUsage */ @Deprecated public Collection<GenericObjectWithDependantsVO> getGenericObjectsMore(Integer iModuleId, List<Integer> lstIds, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, boolean bIncludeParentObjects) { return getGenericObjectsMore(iModuleId, lstIds, stRequiredAttributeIds, stRequiredSubEntityNames, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY), bIncludeParentObjects); } public Collection<GenericObjectWithDependantsVO> getGenericObjectsMore(Integer iModuleId, List<Integer> lstIds, Set<Integer> stRequiredAttributeIds, Set<String> stRequiredSubEntityNames, String customUsage, boolean bIncludeParentObjects) { final EntityMetaDataVO eMeta = MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)); final List<EntityObjectVO> eos = NucletDalProvider.getInstance().getEntityObjectProcessor(eMeta.getEntity()) .getBySearchExpressionAndPrimaryKeys( new CollectableSearchExpression() /*appendRecordGrants(new CollectableSearchExpression(), eMeta) - No check of recordgrants here*/, DalUtils.convertIntegerIdList(lstIds)); List<GenericObjectWithDependantsVO> result = new ArrayList<GenericObjectWithDependantsVO>(eos.size()); for (EntityObjectVO eo : eos) { final GenericObjectWithDependantsVO go = new GenericObjectWithDependantsVO( DalSupportForGO.getGenericObjectVO(eo), new DependantMasterDataMapImpl()); try { _fillDependants(go, go.getUsageCriteria(getAttributeCache(), customUsage), stRequiredSubEntityNames, customUsage); } catch (CommonFinderException e) { throw new NuclosFatalException(e); } result.add(go); } return result; } /** * creates a new generic object, along with its dependants. * @param gowdvo containing the generic object data * @param stRequiredSubEntityNames Set<String> * @return the new generic object, containing the dependants for the specified sub entities. * @throws CommonFinderException * @throws CommonCreateException * @throws CommonPermissionException * @throws NuclosBusinessRuleException * * @precondition gowdvo.getId() == null * @precondition Modules.getInstance().isSubModule(iModuleId.intValue()) --> gowdvo.getParentId() != null * @precondition (gowdvo.getDependants() != null) -> gowdvo.getDependants().dependantsAreNew() * @precondition stRequiredSubEntityNames != null * * @nucleus.permission mayWrite(module) * * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public GenericObjectWithDependantsVO create(GenericObjectWithDependantsVO gowdvo, Set<String> stRequiredSubEntityNames) throws NuclosBusinessRuleException, CommonPermissionException, CommonCreateException, CommonFinderException { return create(gowdvo, stRequiredSubEntityNames, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public GenericObjectWithDependantsVO create(GenericObjectWithDependantsVO gowdvo, Set<String> stRequiredSubEntityNames, String customUsage) throws CommonPermissionException, NuclosBusinessRuleException, CommonCreateException, CommonFinderException { if (stRequiredSubEntityNames == null) { throw new IllegalArgumentException("stRequiredSubEntityNames"); } final GenericObjectVO govoCreated = this.create(gowdvo, customUsage); final GenericObjectWithDependantsVO result = new GenericObjectWithDependantsVO(govoCreated, new DependantMasterDataMapImpl()); _fillDependants(result, result.getUsageCriteria(getAttributeCache(), customUsage), stRequiredSubEntityNames, customUsage); return result; } /** * creates a new generic object, along with its dependants. * @param gowdvo the generic object, along with its dependants. * @return the created object witout dependants. * @throws CommonPermissionException if the current user doesn't have the right to create such an object. * @throws NuclosBusinessRuleException if the object could not be created because a business rule failed. * @throws CommonCreateException if the object could not be created for other reasons, eg. because of a database constraint violation. * * @precondition gowdvo.getId() == null * @precondition Modules.getInstance().isSubModule(gowdvo.getModuleId()) --> gowdvo.getParentId() != null * @precondition (gowdvo.getDependants() != null) --> gowdvo.getDependants().areAllDependantsNew() * * @nucleus.permission mayWrite(module) * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public GenericObjectVO create(GenericObjectWithDependantsVO gowdvo) throws CommonPermissionException, NuclosBusinessRuleException, CommonCreateException { return create(gowdvo, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public GenericObjectVO create(GenericObjectWithDependantsVO gowdvo, String customUsage) throws CommonPermissionException, NuclosBusinessRuleException, CommonCreateException { debug("Entering create(GenericObjectWithDependantsVO)"); if (gowdvo.getId() != null) { throw new IllegalArgumentException("govo.getId()"); } final int iModuleId = gowdvo.getModuleId(); // if (!bMainModuleObject && gowdvo.getParentId() == null) { // throw new NullArgumentException("govo.getParentId"); // } DependantWrapper depWrapper = new DependantWrapper(); depWrapper.setDependants(gowdvo.getDependants()); final boolean useRuleEngineSave = this.getUsesRuleEngine( MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)).getEntity(), RuleEventUsageVO.SAVE_EVENT); final boolean useEventSupports = this.getUsesEventSupports(iModuleId, InsertSupport.name); if (useRuleEngineSave || useEventSupports) { /** @todo check if loccvoResult can safely be ignored */ final RuleObjectContainerCVO loccvoResult = fireSaveEvent(Event.CREATE_BEFORE, gowdvo, depWrapper.getDependants(), false, customUsage); depWrapper.setDependants(loccvoResult.getDependants()); } EntityObjectVO dalVO = DalSupportForGO.wrapGenericObjectVO(gowdvo); dalVO.setVersion(null); dalVO.setCreatedBy(null); dalVO.setCreatedAt(null); final String user = getCurrentUserName(); DalUtils.updateVersionInformation(dalVO, user); dalVO.setId(DalUtils.getNextId()); dalVO.flagNew(); // generate system identifier: final String sCanonicalValueSystemIdentifier = BusinessIDFactory.generateSystemIdentifier(iModuleId); assert !StringUtils.isNullOrEmpty(sCanonicalValueSystemIdentifier); dalVO.getFields().put(NuclosEOField.SYSTEMIDENTIFIER.getMetaData().getField(), sCanonicalValueSystemIdentifier); try { validationSupport.validate(dalVO, depWrapper.getDependants()); NucletDalProvider.getInstance().getEntityObjectProcessor(dalVO.getEntity()).insertOrUpdate(dalVO); Date sysdate = new Date(); /** * new "old" generic object record */ EOGenericObjectVO eogo = new EOGenericObjectVO(); eogo.setId(dalVO.getId()); eogo.setCreatedBy(user); eogo.setCreatedAt(InternalTimestamp.toInternalTimestamp(sysdate)); eogo.setVersion(1); eogo.setChangedBy(user); eogo.setChangedAt(InternalTimestamp.toInternalTimestamp(sysdate)); eogo.setModuleId(IdUtils.toLongId(iModuleId)); eogo.flagNew(); NucletDalProvider.getInstance().getEOGenericObjectProcessor().insertOrUpdate(eogo); helper.trackChangesToLogbook(null, dalVO); } catch (Exception e1) { throw new CommonCreateException(e1); } final Integer id = IdUtils.unsafeToId(dalVO.getId()); final GenericObjectVO goVO = DalSupportForGO.getGenericObjectVO(dalVO); // get default object group assigned to current user Long groupId = getUserGroupId(user); if (groupId != null) { try { this.addToGroup(id, groupId.intValue(), false); } catch (CommonFinderException e) { throw new CommonFatalException(e); } catch (CommonPermissionException e) { checkWriteAllowedForObjectGroup(gowdvo.getModuleId(), null); } } else { checkWriteAllowedForObjectGroup(gowdvo.getModuleId(), null); } // create dependant records from subforms: if (depWrapper.getDependants() != null) { String entityNameByModuleId = Modules.getInstance().getEntityNameByModuleId(gowdvo.getModuleId()); LayoutFacadeLocal layoutFacade = ServerServiceLocator.getInstance().getFacade(LayoutFacadeLocal.class); final Map<EntityAndFieldName, String> collSubEntities = layoutFacade .getSubFormEntityAndParentSubFormEntityNames(entityNameByModuleId, id, false, customUsage); helper.createDependants(Modules.getInstance().getEntityNameByModuleId(iModuleId), id, depWrapper.getDependants(), collSubEntities, customUsage); } // Write a possible origin object into the logbook: final DynamicAttributeVO attrvoOrigin = gowdvo .getAttribute(NuclosEOField.ORIGIN.getMetaData().getId().intValue()); if (attrvoOrigin != null) { createLogbookEntry(id, attrvoOrigin.getAttributeId(), null, null, null, null, null, null, null, null, null, (String) attrvoOrigin.getValue()); } GenericObjectVO result; if (Modules.getInstance().getUsesStateModel(iModuleId)) { // create first state entry of generic object: try { ServiceLocator.getInstance().getFacade(StateFacadeLocal.class).enterInitialState(goVO, depWrapper, customUsage); // NUCLEUSINT-928: result was helper.getValueObject(goVO), see else clause. // But that object represents the object before the state change (version 1) // while the real object in the database is version 2. Beside the version, // some other attributes may have been changed by state transition, too. // TODO: As workaround (because enterInitialState()/StateFacadeBean does not // return the changed object), we get a new one via get(). result = get(id); } catch (NuclosNoAdequateStatemodelException ex) { // This is considered fatal: throw new CommonFatalException(ex.getMessage(), ex); } catch (CommonFinderException ex) { // This is considered fatal: throw new CommonFatalException(ex); } catch (NuclosBusinessException ex) { // This is considered fatal: throw new CommonFatalException(ex.getMessage(), ex); } } else { result = DalSupportForGO.getGenericObject(goVO.getId(), goVO.getModuleId()); } final boolean useRuleEngineSaveAfter = this.getUsesRuleEngine( MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)).getEntity(), RuleEventUsageVO.SAVE_AFTER_EVENT); final boolean useFinalEventSupports = this.getUsesEventSupports(iModuleId, InsertFinalSupport.name); if (useRuleEngineSaveAfter || useFinalEventSupports) { try { // mpDependants = reloadDependants(result, mpDependants, true, customUsage); depWrapper.setDependants( fireSaveEvent(Event.CREATE_AFTER, result, depWrapper.getDependants(), true, customUsage) .getDependants(true)); result = get(id); } catch (CommonFinderException ex) { throw new CommonFatalException(ex); } } debug("Leaving create(GenericObjectWithDependantsVO)"); return result; } private Long getUserGroupId(String sUserName) { DbQueryBuilder builder = dataBaseHelper.getDbAccess().getQueryBuilder(); DbQuery<Long> query = builder.createQuery(Long.class); DbFrom t = query.from("T_MD_USER").alias(SystemFields.BASE_ALIAS); query.select(t.baseColumn("INTID_T_UD_GROUP", Long.class)); query.where(builder.equal(builder.upper(t.baseColumn("STRUSER", String.class)), builder.upper(builder.literal(sUserName)))); Long executeQuerySingleResult = null; try { executeQuerySingleResult = dataBaseHelper.getDbAccess().executeQuerySingleResult(query); } catch (DbInvalidResultSizeException e) { throw new CommonFatalException("Could not find user " + sUserName); } return executeQuerySingleResult; } /** * updates an existing generic object in the database and returns the written object along with its dependants. * @param iModuleId module id for plausibility check * @param lowdcvo containing the generic object data * @return same generic object as value object * @precondition iModuleId != null * @precondition lowdcvo.getModuleId() == iModuleId * @nucleus.permission mayWrite(module) * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public GenericObjectWithDependantsVO modify(Integer iModuleId, GenericObjectWithDependantsVO lowdcvo) throws CommonCreateException, CommonFinderException, CommonRemoveException, CommonPermissionException, CommonStaleVersionException, NuclosBusinessException, CommonValidationException { return modify(iModuleId, lowdcvo, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public GenericObjectWithDependantsVO modify(Integer iModuleId, GenericObjectWithDependantsVO lowdcvo, String customUsage) throws CommonCreateException, CommonFinderException, CommonRemoveException, CommonPermissionException, CommonStaleVersionException, NuclosBusinessException, CommonValidationException { if (iModuleId == null) { throw new NullArgumentException("iModuleId"); } if (lowdcvo.getModuleId() != iModuleId) { throw new IllegalArgumentException("iModuleId"); } final GenericObjectVO govoUpdated = this.modify(lowdcvo, lowdcvo.getDependants(), true, customUsage); final GenericObjectMetaDataCache lometadataprovider = GenericObjectMetaDataCache.getInstance(); final GenericObjectWithDependantsVO result = new GenericObjectWithDependantsVO(govoUpdated, new DependantMasterDataMapImpl()); final UsageCriteria usage = govoUpdated.getUsageCriteria(getAttributeCache(), customUsage); final Set<String> collSubEntityNames = lometadataprovider .getSubFormEntityNamesByLayoutId(lometadataprovider.getBestMatchingLayoutId(usage, false)); _fillDependants(result, usage, collSubEntityNames, customUsage); return result; } /** * modifies an existing generic object. * @param govo containing the generic object data * @param mpDependants Map of dependant masterdata objects. May be <code>null</code>. The dependant objects must * have a field "genericObjectId" filled with their parent's id. * @param bFireSaveEvent * @return same generic object as value object * @nucleus.permission mayWrite(module) * @todo change signature into GenericObjectVO modify(GenericObjectWithDependantsVO lowdcvo, boolean bFireSaveEvent) * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public GenericObjectVO modify(GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean bFireSaveEvent) throws CommonPermissionException, CommonStaleVersionException, NuclosBusinessException, CommonValidationException, CommonCreateException, CommonFinderException, CommonRemoveException { return modify(govo, mpDependants, bFireSaveEvent, true, true, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public GenericObjectVO modify(GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean bFireSaveEvent, String customUsage) throws CommonPermissionException, CommonStaleVersionException, NuclosBusinessException, CommonValidationException, CommonCreateException, CommonFinderException, CommonRemoveException { return modify(govo, mpDependants, bFireSaveEvent, true, true, customUsage); } /** * modifies an existing generic object. * @param govo containing the generic object data * @param mpDependants Map of dependant masterdata objects. May be <code>null</code>. The dependant objects must * have a field "genericObjectId" filled with their parent's id. * @param bFireSaveEvent * @param bCheckPermission * @return same generic object as value object * @nucleus.permission mayWrite(module) * @todo change signature into GenericObjectVO modify(GenericObjectWithDependantsVO lowdcvo, boolean bFireSaveEvent) * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public GenericObjectVO modify(GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean bFireSaveEvent, boolean bCheckPermission) throws CommonPermissionException, CommonStaleVersionException, NuclosBusinessException, CommonValidationException, CommonCreateException, CommonFinderException, CommonRemoveException { return modify(govo, mpDependants, bFireSaveEvent, bCheckPermission, true, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public GenericObjectVO modify(GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean bFireSaveEvent, boolean bCheckPermission, boolean bReadDependants, String customUsage) throws CommonPermissionException, CommonStaleVersionException, NuclosBusinessException, CommonValidationException, CommonCreateException, CommonFinderException, CommonRemoveException { // @todo make the handling of mpDependants clean! this.debug("Entering modify(GenericObjectVO govo, DependantMasterDataMap mpDependants)"); final GenericObjectVO dbGoVO_new; final Integer newId; this.debug("Modifying (Start find)"); EntityObjectVO dbEoVO = DalSupportForGO.getEntityObject(govo.getId(), govo.getModuleId()); GenericObjectVO dbGoVO = DalSupportForGO.getGenericObjectVO(dbEoVO); if (bCheckPermission) { this.checkWriteAllowedForModule(govo.getModuleId(), govo.getId()); getRecordGrantUtils().checkWriteInternal(dbEoVO.getEntity(), dbEoVO.getId()); } this.checkForStaleVersion(dbGoVO, govo); final boolean useRuleEngineSave = this.getUsesRuleEngine( MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(govo.getModuleId())).getEntity(), RuleEventUsageVO.SAVE_EVENT); final boolean useEventSupports = this.getUsesEventSupports(govo.getModuleId(), UpdateSupport.name); if (bFireSaveEvent && (useRuleEngineSave || useEventSupports)) { this.debug("Modifying (Start rules)"); final RuleObjectContainerCVO loccvoResult = this.fireSaveEvent(Event.MODIFY_BEFORE, govo, mpDependants, false, customUsage); govo = loccvoResult.getGenericObject(); mpDependants = loccvoResult.getDependants(true); } this.debug("Modifying (Start change genericobject)"); EntityObjectVO eoUpdated = DalSupportForGO.wrapGenericObjectVO(govo); validationSupport.validate(eoUpdated, mpDependants); DalUtils.updateVersionInformation(eoUpdated, getCurrentUserName()); eoUpdated.flagUpdate(); try { NucletDalProvider.getInstance().getEntityObjectProcessor(eoUpdated.getEntity()) .insertOrUpdate(eoUpdated); } catch (DbException e) { throw new NuclosBusinessException(e); } helper.trackChangesToLogbook(dbEoVO, eoUpdated); if (mpDependants != null) { this.debug("Modifying (Start change dependants)"); String entityNameByModuleId = Modules.getInstance().getEntityNameByModuleId(govo.getModuleId()); LayoutFacadeLocal layoutFacade = ServerServiceLocator.getInstance().getFacade(LayoutFacadeLocal.class); final Map<EntityAndFieldName, String> collSubEntities = layoutFacade .getSubFormEntityAndParentSubFormEntityNames(entityNameByModuleId, govo.getId(), false, customUsage); mpDependants.setParent(entityNameByModuleId, govo.getId(), collSubEntities); // First protocol all the modified records final Set<Integer> stExcluded = new HashSet<Integer>(); getMasterDataFacade().protocolDependantChanges(govo.getId(), mpDependants, stExcluded, false); if (bReadDependants) { for (String sEntityName : mpDependants.getEntityNames()) { for (EntityObjectVO mdVO : mpDependants.getData(sEntityName)) { getMasterDataFacade().readAllDependants(sEntityName, IdUtils.unsafeToId(mdVO.getId()), mdVO.getDependants(), mdVO.isFlagRemoved(), sEntityName, collSubEntities); } } } getMasterDataFacade().modifyDependants(entityNameByModuleId, govo.getId(), govo.isRemoved(), mpDependants, bReadDependants, customUsage); // .. and then all the newly created ones, excluding the already written (i.e. the modified). getMasterDataFacade().protocolDependantChanges(govo.getId(), mpDependants, stExcluded, true); } this.debug("Modifying (Start read)"); GenericObjectVO result = get(dbGoVO.getId()); final boolean useRuleEngineSaveAfter = this.getUsesRuleEngine( MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(govo.getModuleId())).getEntity(), RuleEventUsageVO.SAVE_AFTER_EVENT); final boolean useFinalEventSupports = this.getUsesEventSupports(govo.getModuleId(), UpdateFinalSupport.name); if (bFireSaveEvent && (useRuleEngineSaveAfter || useFinalEventSupports)) { this.debug("Modifying (Start rules after save)"); mpDependants = reloadDependants(result, mpDependants, true, customUsage); this.fireSaveEvent(Event.MODIFY_AFTER, result, mpDependants, true, customUsage); result = get(dbGoVO.getId()); } this.debug("Leaving modify(GenericObjectVO govo, DependantMasterDataMap mpDependants)"); return result; } /** * fires a Save event, executing the corresponding business rules. * @param govo * @param mpDependants * @return * @throws CreateException * @throws NuclosBusinessRuleException * @precondition Modules.getInstance().getUsesRuleEngine(govo.getModuleId().intValue()) */ private RuleObjectContainerCVO fireSaveEvent(Event event, GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean after, String customUsage) throws NuclosBusinessRuleException { if (!Modules.getInstance().getUsesRuleEngine(govo.getModuleId())) { throw new IllegalArgumentException("govo.getModuleId()"); } EventSupportFacadeLocal evSuppFacade = ServerServiceLocator.getInstance() .getFacade(EventSupportFacadeLocal.class); RuleEngineFacadeLocal facade = ServerServiceLocator.getInstance().getFacade(RuleEngineFacadeLocal.class); String sEntity = Modules.getInstance().getEntityNameByModuleId(govo.getModuleId()); RuleObjectContainerCVO retVal = facade.fireRule(sEntity, after ? RuleEventUsageVO.SAVE_AFTER_EVENT : RuleEventUsageVO.SAVE_EVENT, new RuleObjectContainerCVOImpl(event, govo, mpDependants != null ? mpDependants : new DependantMasterDataMapImpl()), null); String sSupportType = null; if (event.equals(Event.CREATE_AFTER)) sSupportType = InsertFinalSupport.name; else if (event.equals(Event.CREATE_BEFORE)) sSupportType = InsertSupport.name; else if (event.equals(Event.MODIFY_AFTER)) sSupportType = UpdateFinalSupport.name; else if (event.equals(Event.MODIFY_BEFORE)) sSupportType = UpdateSupport.name; retVal = evSuppFacade.fireSaveEventSupport(govo.getModuleId(), sSupportType, retVal); return retVal; } /** * fires a Delete event, executing the corresponding business rules. * @param govo * @param mpDependants * @return * @throws CreateException * @throws NuclosBusinessRuleException * @precondition Modules.getInstance().getUsesRuleEngine(govo.getModuleId()) */ private void fireDeleteEvent(GenericObjectVO govo, DependantMasterDataMap mpDependants, boolean after, String customUsage) throws NuclosBusinessRuleException { if (!Modules.getInstance().getUsesRuleEngine(govo.getModuleId())) { throw new IllegalArgumentException("govo.getModuleId()"); } String sEntityName = Modules.getInstance().getEntityNameByModuleId(govo.getModuleId()); RuleObjectContainerCVO ruleObjectContainerCVO = new RuleObjectContainerCVOImpl( after ? Event.DELETE_AFTER : Event.DELETE_BEFORE, govo, mpDependants != null ? mpDependants : new DependantMasterDataMapImpl()); RuleEngineFacadeLocal facade = ServerServiceLocator.getInstance().getFacade(RuleEngineFacadeLocal.class); facade.fireRule(sEntityName, after ? RuleEventUsageVO.DELETE_AFTER_EVENT : RuleEventUsageVO.DELETE_EVENT, ruleObjectContainerCVO, null); EventSupportFacadeLocal evSuppFacade = ServerServiceLocator.getInstance() .getFacade(EventSupportFacadeLocal.class); String sSupportType = null; if (after) { sSupportType = DeleteSupport.name; } else { sSupportType = DeleteFinalSupport.name; } final UsageCriteria usage = govo.getUsageCriteria(getAttributeCache(), customUsage); evSuppFacade.fireDeleteEventSupport(govo.getModuleId(), sSupportType, usage, ruleObjectContainerCVO, true); } /** * delete generic object from database * @param gowdvo containing the generic object data * @param bDeletePhysically remove from db? * @throws NuclosBusinessRuleException * @throws CommonCreateException * @nucleus.permission mayDelete(module, bDeletePhysically) * @Deprecated use with customUsage */ @RolesAllowed("Login") @Deprecated public void remove(GenericObjectWithDependantsVO gowdvo, boolean bDeletePhysically) throws NuclosBusinessException, CommonFinderException, CommonRemoveException, CommonPermissionException, CommonStaleVersionException, NuclosBusinessRuleException, CommonCreateException { remove(gowdvo, bDeletePhysically, ServerParameterProvider.getInstance().getValue(ParameterProvider.KEY_LAYOUT_CUSTOM_KEY)); } @RolesAllowed("Login") public void remove(GenericObjectWithDependantsVO gowdvo, boolean bDeletePhysically, String customUsage) throws NuclosBusinessException, CommonFinderException, CommonRemoveException, CommonPermissionException, CommonStaleVersionException, NuclosBusinessRuleException, CommonCreateException { this.debug("Entering remove(GenericObjectWithDependantsVO gowdvo, boolean bDeletePhysically)"); final int iModuleId; LayoutFacadeLocal layoutFacade = ServerServiceLocator.getInstance().getFacade(LayoutFacadeLocal.class); // try { // final GenericObjectVO dbGoVO = MasterDataWrapper.getGenericObjectVO(getMasterDataFacade().get(NuclosEntity.GENERICOBJECT.getEntityName(), gowdvo.getId())); final GenericObjectVO dbGoVO = DalSupportForGO.getGenericObject(gowdvo.getId(), gowdvo.getModuleId()); iModuleId = dbGoVO.getModuleId(); String entity = MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)).getEntity(); this.checkDeleteAllowedForModule(iModuleId, dbGoVO.getId(), bDeletePhysically); getRecordGrantUtils().checkDeleteInternal(entity, IdUtils.toLongId(dbGoVO.getId())); // prevent removal if dependant dynamic attributes exist: final Object oExternalId = gowdvo.getId(); if (oExternalId == null) { throw new NuclosFatalException("genericobject.facade.exception.2");//"Der Datensatz hat eine leere Id."); } // if (oExternalId instanceof Integer) { // checkDependantAttributeValues((Integer) oExternalId); // } this.checkForStaleVersion(dbGoVO, gowdvo); // Is the object to delete a main module (as opposed to submodule) object? // final boolean bMainModuleObject = Modules.getInstance().isMainModule(gowdvo.getModuleId()); // // if (!bMainModuleObject && gowdvo.getParentId() == null) { // throw new NullArgumentException("gowdvo.getParentId"); // } // load and set all attributes of given gowdvo, to have access on them within rules gowdvo.addAndSetAttribute(dbGoVO.getAttributes()); DependantMasterDataMap mpDependants = gowdvo.getDependants(); if (!bDeletePhysically) // NUCLOSINT-890 gowdvo.setDeleted(true); // Only set deleted if logical deleted. This could be be useful in rules. final Map<EntityAndFieldName, String> collSubEntities = layoutFacade .getSubFormEntityAndParentSubFormEntityNames( Modules.getInstance().getEntityNameByModuleId(dbGoVO.getModuleId()), dbGoVO.getId(), false, customUsage); final boolean useRuleEngineDelete = this.getUsesRuleEngine( MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)).getEntity(), RuleEventUsageVO.DELETE_EVENT); final boolean useEventSupports = this.getUsesEventSupports(iModuleId, DeleteSupport.name); if (useRuleEngineDelete || useEventSupports) { this.fireDeleteEvent(gowdvo, gowdvo.getDependants(), false, customUsage); } final UsageCriteria usage = gowdvo.getUsageCriteria(getAttributeCache(), customUsage); DalCallResult dalResult; if (bDeletePhysically) { //@see NUCLOS-708. clear dependants map first. for (String sDependantEntityName : new ArrayList<String>(gowdvo.getDependants().getEntityNames())) { gowdvo.getDependants().setData(sDependantEntityName, new ArrayList<EntityObjectVO>(0)); } _fillDependants(gowdvo, usage, new HashSet<String>(), customUsage); for (EntityAndFieldName eafn : collSubEntities.keySet()) { // care only about subforms which are on the highest level if (collSubEntities.get(eafn) == null) { // mark all dependant data as removed for (EntityObjectVO mdVO : gowdvo.getDependants().getData(eafn.getEntityName())) { mdVO.flagRemove(); getMasterDataFacade().readAllDependants(eafn.getEntityName(), IdUtils.unsafeToId(mdVO.getId()), mdVO.getDependants(), mdVO.isFlagRemoved(), eafn.getEntityName(), collSubEntities); } } } // remove dependant data masterDataFacadeHelper.removeDependants(gowdvo.getDependants(), customUsage); removeDependants(dbGoVO, customUsage); helper.removeLogBookEntries(dbGoVO.getId()); helper.removeDependantTaskObjects(dbGoVO.getId()); helper.removeGroupBelonging(dbGoVO.getId()); // getMasterDataFacade().remove(NuclosEntity.GENERICOBJECT.getEntityName(), MasterDataWrapper.wrapGenericObjectVO(dbGoVO), false); try { NucletDalProvider.getInstance().getEOGenericObjectProcessor() .delete(IdUtils.toLongId(dbGoVO.getId())); DalSupportForGO.getEntityObjectProcessor(dbGoVO.getModuleId()) .delete(IdUtils.toLongId(dbGoVO.getId())); } catch (DbException e) { throw new NuclosBusinessException(e); } } else { // dbGoVO.setDeleted(true); // getMasterDataFacade().modify(NuclosEntity.GENERICOBJECT.getEntityName(), MasterDataWrapper.wrapGenericObjectVO(dbGoVO), null); EntityObjectVO eoToUpdate = DalSupportForGO.wrapGenericObjectVO(dbGoVO); helper.createLogBookEntryIfNecessary(eoToUpdate, null, new DynamicAttributeVO( IdUtils.unsafeToId(NuclosEOField.LOGGICALDELETED.getMetaData().getId()), null, Boolean.TRUE)); eoToUpdate.getFields().put(NuclosEOField.LOGGICALDELETED.getMetaData().getField(), Boolean.TRUE); DalUtils.updateVersionInformation(eoToUpdate, getCurrentUserName()); eoToUpdate.flagUpdate(); try { DalSupportForGO.getEntityObjectProcessor(dbGoVO.getModuleId()).insertOrUpdate(eoToUpdate); } catch (DbException e) { throw new NuclosBusinessException(e); } } // } // catch (CommonValidationException ex) { // throw new CommonFatalException(ex); // } if (isInfoEnabled()) { info("The entry " + gowdvo.getSystemIdentifier() + " (Id: " + gowdvo.getId() + ") has been deleted."); } final boolean useRuleEngineDeleteAfter = this.getUsesRuleEngine( MetaDataServerProvider.getInstance().getEntity(IdUtils.toLongId(iModuleId)).getEntity(), RuleEventUsageVO.DELETE_AFTER_EVENT); final boolean useFinalEventSupports = this.getUsesEventSupports(iModuleId, DeleteFinalSupport.name); if (useRuleEngineDeleteAfter || useFinalEventSupports) { this.fireDeleteEvent(gowdvo, gowdvo.getDependants(), true, customUsage); } this.debug("Leaving remove(GenericObjectVO govo, boolean bDeletePhysically)"); } /** * update generic object in database * @param sEntityName name of the entity * @throws NuclosBusinessRuleException */ @RolesAllowed("Login") public void updateGenericObjectEntries(String sEntityName) throws NuclosBusinessException { this.debug("Entering updateGenericObjectEntries(String sEntityName)"); Integer iModuleId = null; if (Modules.getInstance().isModuleEntity(sEntityName)) iModuleId = Modules.getInstance().getModuleIdByEntityName(sEntityName); else iModuleId = IdUtils.unsafeToId(MetaDataServerProvider.getInstance().getEntity(sEntityName).getId()); if (!Modules.getInstance().isModuleEntity(sEntityName)) { List<Integer> lstGenericObjectIds = getGenericObjectIds(iModuleId, (CollectableSearchCondition) null); for (Integer id : lstGenericObjectIds) { // @todo helper.removeLogBookEntries(id); helper.removeDependantTaskObjects(id); helper.removeGroupBelonging(id); try { NucletDalProvider.getInstance().getEOGenericObjectProcessor().delete(IdUtils.toLongId(id)); } catch (DbException e) { throw new NuclosBusinessException(e); } } } else { CollectableSearchCondition cond = new CollectableIsNullCondition( new CollectableEOEntityField(NuclosEOField.SYSTEMIDENTIFIER.getMetaData(), sEntityName)); TruncatableCollection<MasterDataVO> mdcvos = masterDataFacadeHelper.getGenericMasterData(sEntityName, cond, true); for (MasterDataVO mdvo : mdcvos) { EOGenericObjectVO eoGenericObjectVO = new EOGenericObjectVO(); eoGenericObjectVO.flagNew(); eoGenericObjectVO.setId(IdUtils.toLongId(mdvo.getIntId())); eoGenericObjectVO.setModuleId(IdUtils.toLongId(iModuleId)); DalUtils.updateVersionInformation(eoGenericObjectVO, getCurrentUserName()); try { NucletDalProvider.getInstance().getEOGenericObjectProcessor().insertOrUpdate(eoGenericObjectVO); EntityObjectVO dalVO = DalSupportForGO.getEntityObjectProcessor(iModuleId) .getByPrimaryKey(IdUtils.toLongId(mdvo.getIntId())); final String sCanonicalValueSystemIdentifier = BusinessIDFactory .generateSystemIdentifier(iModuleId); assert !StringUtils.isNullOrEmpty(sCanonicalValueSystemIdentifier); dalVO.getFields().put(NuclosEOField.SYSTEMIDENTIFIER.getMetaData().getField(), sCanonicalValueSystemIdentifier); dalVO.flagUpdate(); DalSupportForGO.getEntityObjectProcessor(iModuleId).insertOrUpdate(dalVO); } catch (DbException e) { throw new NuclosBusinessException(e); } } } this.debug("Leaving updateGenericObjectEntries(String sEntityName)"); } // replaces the ejbRemove() from GenericObjectBean private void removeDependants(GenericObjectVO govo, String customUsage) throws CommonFinderException, CommonPermissionException, NuclosBusinessRuleException, CommonStaleVersionException, CommonRemoveException { final int iModuleId = govo.getModuleId(); final Modules modules = Modules.getInstance(); // delete all dependant leased object relations: for (GenericObjectRelationVO vo : findRelationsByGenericObjectId(govo.getId())) { getMasterDataFacade().remove(NuclosEntity.GENERICOBJECTRELATION.getEntityName(), MasterDataWrapper.wrapGenericObjectRelationVO(vo), false, customUsage); } if (modules.getUsesStateModel(iModuleId)) { // delete all dependant state history entries: StateFacadeLocal stateFacade = ServerServiceLocator.getInstance().getFacade(StateFacadeLocal.class); for (StateHistoryVO history : stateFacade.findStateHistoryByGenericObjectId(govo.getId())) { getMasterDataFacade().remove(NuclosEntity.STATEHISTORY.getEntityName(), MasterDataWrapper.wrapStateHistoryVO(history), false, customUsage); } } if (modules.isLogbookTracking(iModuleId)) { dataBaseHelper.getDbAccess() .execute(DbStatementUtils.deleteFrom("T_UD_LOGBOOK", "INTID_T_UD_GENERICOBJECT", govo.getId())); } } /** * restore GO marked as deleted * @param gowdvo containing the generic object data * @throws CommonFinderException * @throws CommonRemoveException * @throws CommonPermissionException * @throws CommonStaleVersionException * @throws NuclosBusinessRuleException * @throws CommonCreateException */ public void restore(Integer iId, String customUsage) throws CommonFinderException, CommonPermissionException, CommonBusinessException { this.debug("Entering restore(GenericObjectWithDependantsVO gowdvo)"); GenericObjectWithDependantsVO goVO = this.getWithDependants(iId, null, customUsage); goVO.setDeleted(false); this.modify(getModuleContainingGenericObject(iId), goVO, customUsage); // NUCLOSINT-890 this.debug("Leaving retstore(GenericObjectVO govo)"); } /** * Checks if dependant attribute values exist that refer to the given external id. * @param iExternalId * @throws CommonRemoveException if dependant attribute values exist. */ // static void checkDependantAttributeValues(Integer iExternalId) throws CommonRemoveException { // final String sSql = "select intid_t_md_attribute from T_UD_GO_ATTRIBUTE a " + // "join T_UD_GENERICOBJECT g on (g.intid = a.intid_t_ud_genericobject) " + // "where a.intid_external = " + iExternalId + " and g.intid = a.intid_t_ud_genericobject and g.blndeleted <> 1"; // // final Integer iAttributeId = NuclosSQLUtils.runSelect(NuclosDataSources.getDefaultDS(), sSql, new GetSingleIntegerOrDefault(null)); // if (iAttributeId != null) { // final AttributeCVO attrcvo = attributeCache.getAttribute(iAttributeId); // throw new CommonRemoveException(StringUtils.getParameterizedExceptionMessage("genericobject.error.validation.attributes", // attrcvo.getName(), attrcvo.getResourceSIdForLabel())); // } // } /** * method to get logbook entries for a generic object * * @param iGenericObjectId id of generic object to get logbook entries for * @param iAttributeId id of attribute to get logbook entries for * @return collection of logbook entry value objects * @precondition Modules.getInstance().isLogbookTracking(this.getModuleContainingGenericObject(iGenericObjectId)) * @nucleus.permission mayRead(module) */ @RolesAllowed("Login") public Collection<LogbookVO> getLogbook(int iGenericObjectId, Integer iAttributeId) throws CommonFinderException, CommonPermissionException { final int iModuleId = this.getModuleContainingGenericObject(iGenericObjectId); if (!Modules.getInstance().isLogbookTracking(iModuleId)) { throw new CommonFatalException("genericobject.facade.exception.3"); // "F\u00fcr diese Modulentit\u00e4t ist die Logbuchfunktion ausgeschaltet.\n"+ // "Um die Statushistorie f\u00fcr diese Entit\u00e4t zu verwenden, aktivieren Sie bitte die Logbuchfunktion\n"+ // "in der Administrationsmaske f\u00fcr Modulentit\u00e4ten."); } this.checkReadAllowedForModule(iModuleId, iGenericObjectId); final Collection<LogbookVO> result = new HashSet<LogbookVO>(); MasterDataMetaVO metaVO = MasterDataMetaCache.getInstance().getMetaData(NuclosEntity.GENERICOBJECTLOGBOOK); CollectableSearchCondition cond = SearchConditionUtils.newMDReferenceComparison(metaVO, "genericObject", iGenericObjectId); if (iAttributeId != null) { cond = SearchConditionUtils.and(cond, SearchConditionUtils.newMDReferenceComparison(metaVO, "attribute", iAttributeId)); } Collection<MasterDataVO> logbook = getMasterDataFacade() .getMasterData(NuclosEntity.GENERICOBJECTLOGBOOK.getEntityName(), cond, true); for (MasterDataVO mdVO : logbook) { final Integer iAttributeIdLogbook = mdVO.getField("attributeId", Integer.class); if (iAttributeIdLogbook == null) { addLogbookIfPossible(result, mdVO); } else if (!getAttributeCache().contains(iAttributeIdLogbook)) { // This may be the case when there is an old attribute entry in the logbook: addLogbookIfPossible(result, mdVO); } else { /** @todo consider attribute group permissions here ! */ final AttributeCVO attrcvo = getAttributeCache().getAttribute(iAttributeIdLogbook); if (attrcvo .isLogbookTracking()/*&& (SecurityCache.getInstance().getAttributegroupsRO(getCurrentUserName()).contains(attrcvo.getAttributegroupId()))*/) { addLogbookIfPossible(result, mdVO); } } } return result; } private void addLogbookIfPossible(final Collection<LogbookVO> result, MasterDataVO mdVO) { try { result.add(MasterDataWrapper.getLogbookVO(mdVO)); } catch (Exception e) { // logbook entry can't be added; skip value LOG.info("addLogbookIfPossible: " + e); } } /** * adds the generic object with the given id to the group with the given id. * @param iGenericObjectId generic object id to be grouped. Must be a main module object. * @param iGroupId id of group to add generic object to * @param blnCheckWriteAllowedForObject ; should only be set to false when creating a new generic object, otherwise always true * @throws NuclosBusinessRuleException * @nucleus.permission mayWrite(module) */ @RolesAllowed("Login") public void addToGroup(int iGenericObjectId, int iGroupId, boolean blnCheckWriteAllowedForObject) throws CommonCreateException, CommonFinderException, CommonPermissionException, NuclosBusinessRuleException { final int iModuleId = this.getModuleContainingGenericObject(iGenericObjectId); this.checkWriteAllowedForObjectGroup(iModuleId, iGroupId); if (blnCheckWriteAllowedForObject) { this.checkWriteAllowedForModule(iModuleId, iGenericObjectId); } // XXX* this.gogrouphome.create(iGroupId, iGenericObjectId); GenericObjectGroupFacadeLocal goGroupFacade = ServerServiceLocator.getInstance() .getFacade(GenericObjectGroupFacadeLocal.class); goGroupFacade.addToGroup(iGenericObjectId, iGroupId); } /** * removes the list of generic objects with the given id from the group with the given id. * @param mpGOGroupRelation * @throws CommonCreateException * @throws CommonStaleVersionException * @throws CommonRemoveException * @throws CommonPermissionException * @throws CommonFinderException * @throws NuclosBusinessRuleException * @throws CommonRemoveException * @throws CommonFinderException * @throws CommonPermissionException * @nucleus.permission mayWrite(targetModule) */ @RolesAllowed("Login") public void removeFromGroup(Map<Integer, Integer> mpGOGroupRelation) throws NuclosBusinessRuleException, CommonFinderException, CommonPermissionException, CommonRemoveException, CommonStaleVersionException, CommonCreateException { for (Integer iGenericObjectId : mpGOGroupRelation.keySet()) { this.removeFromGroup(iGenericObjectId, mpGOGroupRelation.get(iGenericObjectId)); } } /** * removes the generic object with the given id from the group with the given id. * @param iGenericObjectId generic object id to be removed. Must be a main module object. * @param iGroupId id of group to remove generic object from * @throws CommonFinderException * @throws CommonPermissionException * @throws CreateException * @throws CommonCreateException * @throws CommonStaleVersionException * @throws CommonRemoveException * @throws NuclosBusinessRuleException * @nucleus.permission mayWrite(module) */ @RolesAllowed("Login") public void removeFromGroup(int iGenericObjectId, int iGroupId) throws CommonFinderException, CommonPermissionException, NuclosBusinessRuleException, CommonRemoveException, CommonStaleVersionException, CommonCreateException { final int iModuleId = this.getModuleContainingGenericObject(iGenericObjectId); checkWriteAllowedForObjectGroup(iModuleId, iGroupId); GenericObjectGroupFacadeLocal goGroupFacade = ServerServiceLocator.getInstance() .getFacade(GenericObjectGroupFacadeLocal.class); goGroupFacade.removeFromGroup(iGenericObjectId, iGroupId); } /** * relates a generic object to another generic object. * @param iModuleIdTarget module id of target generic object to be related * @param iGenericObjectIdTarget id of target generic object to be related * @param iGenericObjectIdSource id of source generic object to be related to * @param relationType relation type * @precondition isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget) * @precondition Modules.getInstance().isMainModule(iModuleIdTarget.intValue()) * @nucleus.permission mayWrite(targetModule) */ @RolesAllowed("Login") public void relate(Integer iModuleIdTarget, Integer iGenericObjectIdTarget, Integer iGenericObjectIdSource, String relationType) throws CommonFinderException, CommonCreateException, CommonPermissionException, NuclosBusinessRuleException { this.relate(iModuleIdTarget, iGenericObjectIdTarget, iGenericObjectIdSource, relationType, null, null, null); } /** * relates a generic object to another generic object. * @param iModuleIdTarget module id of target generic object to be related (i.e. of request) * @param iGenericObjectIdTarget id of target generic object to be related (i.e. request) * @param iGenericObjectIdSource id of source generic object to be related to (i.e. demand) * @param relationType relation type * @param dateValidFrom Must be <code>null</code> for system defined relation types. * @param dateValidUntil Must be <code>null</code> for system defined relation types. * @param sDescription Must be <code>null</code> for system defined relation types. * @precondition isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget) * @precondition Modules.getInstance().isMainModule(iModuleIdTarget.intValue()) * @nucleus.permission mayWrite(targetModule) */ @RolesAllowed("Login") public void relate(Integer iModuleIdTarget, Integer iGenericObjectIdTarget, Integer iGenericObjectIdSource, String relationType, Date dateValidFrom, Date dateValidUntil, String sDescription) throws CommonFinderException, CommonCreateException, CommonPermissionException, NuclosBusinessRuleException { if (!isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget)) { throw new IllegalArgumentException("iModuleIdTarget"); } //this.checkWriteAllowedForModule(iModuleIdTarget, iGenericObjectIdSource); // why do we have do check if write is allowed here. ?? especially we have to have the sourceModuleId here - not the moduleId from the target this.checkWriteAllowedForModule(iModuleIdTarget, iGenericObjectIdTarget); GenericObjectRelationVO relationVO = new GenericObjectRelationVO(new NuclosValueObject(), iGenericObjectIdSource, iGenericObjectIdTarget, relationType, dateValidFrom, dateValidUntil, sDescription); getMasterDataFacade().create(NuclosEntity.GENERICOBJECTRELATION.getEntityName(), MasterDataWrapper.wrapGenericObjectRelationVO(relationVO), null, null); } /** * removes the relation with the given id. * @param mpGOTreeNodeRelation * @throws CommonRemoveException * @throws CommonFinderException * @throws CommonPermissionException * @nucleus.permission mayWrite(targetModule) */ @RolesAllowed("Login") public void removeRelation(Map<Integer, GenericObjectTreeNode> mpGOTreeNodeRelation) throws CommonBusinessException, CommonRemoveException, CommonFinderException { for (Integer iRelationId : mpGOTreeNodeRelation.keySet()) { this.removeRelation(iRelationId, mpGOTreeNodeRelation.get(iRelationId).getId(), mpGOTreeNodeRelation.get(iRelationId).getModuleId()); } } /** * removes the relation with the given id. * Note that only the relation id is really needed, the other arguments are for security only. * @param iRelationId the id of the relation * @param iGenericObjectIdTarget the id of the target object * @param iModuleIdTarget the module id of the target object * @throws CommonRemoveException * @throws CommonFinderException * @precondition isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget) * @precondition Modules.getInstance().isMainModule(iModuleIdTarget) * @nucleus.permission mayWrite(targetModule) */ @RolesAllowed("Login") public void removeRelation(Integer iRelationId, Integer iGenericObjectIdTarget, Integer iModuleIdTarget) throws CommonRemoveException, CommonFinderException, CommonBusinessException { if (!isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget)) { throw new IllegalArgumentException("iModuleIdTarget"); } this.checkWriteAllowedForModule(iModuleIdTarget, iGenericObjectIdTarget); try { MasterDataVO mdVO = getMasterDataFacade().get(NuclosEntity.GENERICOBJECTRELATION.getEntityName(), iRelationId); GenericObjectRelationVO relationVO = MasterDataWrapper.getGenericObjectRelationVO(mdVO); if (!relationVO.getDestinationGOId().equals(iGenericObjectIdTarget)) { throw new IllegalArgumentException("iGenericObjectIdTarget and iRelationId don't match."); } this.checkWriteAllowedForModule(iModuleIdTarget, relationVO.getSourceGOId()); getMasterDataFacade().remove(NuclosEntity.GENERICOBJECTRELATION.getEntityName(), mdVO, false, null); } catch (CommonPermissionException ex) { throw new CommonBusinessException(ex); } catch (CommonStaleVersionException ex) { throw new CommonBusinessException(ex); } } /** * unrelates a generic object from another generic object. All relations between these objects with the given * relation type are removed. * @param iModuleIdTarget module id of target generic object to be unrelated (i.e. request) * @param iGenericObjectIdTarget id of target generic object to be unrelated (i.e. request) * @param iGenericObjectIdSource id of source generic object to be unrelated (i.e. demand) * @param relationType * @precondition isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget) * @precondition Modules.getInstance().isMainModule(iModuleIdTarget.intValue()) * @nucleus.permission mayWrite(targetModule) */ public void unrelate(Integer iModuleIdTarget, Integer iGenericObjectIdTarget, Integer iGenericObjectIdSource, String relationType) throws CommonFinderException, NuclosBusinessRuleException, CommonPermissionException, CommonRemoveException { if (!isGenericObjectInModule(iModuleIdTarget, iGenericObjectIdTarget)) { throw new IllegalArgumentException("iModuleIdTarget"); } this.checkWriteAllowedForModule(iModuleIdTarget, iGenericObjectIdSource); this.checkWriteAllowedForModule(iModuleIdTarget, iGenericObjectIdTarget); try { for (GenericObjectRelationVO vo : findRelations(iGenericObjectIdSource, relationType, iGenericObjectIdTarget)) { getMasterDataFacade().remove(NuclosEntity.GENERICOBJECTRELATION.getEntityName(), MasterDataWrapper.wrapGenericObjectRelationVO(vo), false, null); } } catch (CommonStaleVersionException ex) { throw new NuclosFatalException(ex); } } /** * finds relations between two given generic objects. * @param iGenericObjectIdSource * @param relationType * @param iGenericObjectIdTarget * @return the relation. * @throws FinderException if no such relation exists. * @postcondition result != null */ public Collection<GenericObjectRelationVO> findRelations(Integer iGenericObjectIdSource, String relationType, Integer iGenericObjectIdTarget) throws CommonFinderException, CommonPermissionException { DbQueryBuilder builder = dataBaseHelper.getDbAccess().getQueryBuilder(); DbQuery<Integer> query = builder.createQuery(Integer.class); DbFrom t = query.from("T_UD_GO_RELATION").alias(SystemFields.BASE_ALIAS); query.select(t.baseColumn("INTID", Integer.class)); query.where( builder.and(builder.equal(t.baseColumn("INTID_T_UD_GO_1", Integer.class), iGenericObjectIdSource), builder.equal(t.baseColumn("INTID_T_UD_GO_2", Integer.class), iGenericObjectIdTarget), builder.equal(t.baseColumn("STRRELATIONTYPE", String.class), relationType))); return findRelationsImpl(query); } public Collection<GenericObjectRelationVO> findRelationsByGenericObjectId(Integer iGenericObjectId) throws CommonFinderException, CommonPermissionException { DbQueryBuilder builder = dataBaseHelper.getDbAccess().getQueryBuilder(); DbQuery<Integer> query = builder.createQuery(Integer.class); DbFrom t = query.from("T_UD_GO_RELATION").alias(SystemFields.BASE_ALIAS); query.select(t.baseColumn("INTID", Integer.class)); query.where(builder.or(builder.equal(t.baseColumn("INTID_T_UD_GO_1", Integer.class), iGenericObjectId), builder.equal(t.baseColumn("INTID_T_UD_GO_2", Integer.class), iGenericObjectId))); return findRelationsImpl(query); } private Collection<GenericObjectRelationVO> findRelationsImpl(DbQuery<Integer> query) throws CommonFinderException, CommonPermissionException { Collection<GenericObjectRelationVO> result = new ArrayList<GenericObjectRelationVO>(); for (Integer id : dataBaseHelper.getDbAccess().executeQuery(query.distinct(true))) result.add(MasterDataWrapper.getGenericObjectRelationVO( getMasterDataFacade().get(NuclosEntity.GENERICOBJECTRELATION.getEntityName(), id))); return result; } /** * checks if a given generic object belongs to a given module. * @param iModuleId id of module to validate generic object for * @param iGenericObjectId id of generic object to check * @return true if in module or false if not */ public boolean isGenericObjectInModule(Integer iModuleId, Integer iGenericObjectId) throws CommonFinderException { return LangUtils.equals(this.getModuleContainingGenericObject(iGenericObjectId), iModuleId); } /** * @param iGenericObjectId * @return the id of the module containing the generic object with the given id. * @throws CommonFinderException if there is no generic object with the given id. */ @RolesAllowed("Login") public int getModuleContainingGenericObject(int iGenericObjectId) throws CommonFinderException { final EOGenericObjectVO eogo = NucletDalProvider.getInstance().getEOGenericObjectProcessor() .getByPrimaryKey(IdUtils.toLongId(iGenericObjectId)); if (eogo == null) { throw new CommonFinderException(); } if (eogo.getModuleId() == null) { throw new CommonFatalException("moduleId is null"); } return IdUtils.unsafeToId(eogo.getModuleId()); } /** * @param iGenericObjectId * @return the id of the state of the generic object with the given id * @throws CommonFinderException */ @RolesAllowed("Login") public int getStateIdByGenericObject(int iGenericObjectId) throws CommonFinderException { final Integer iAttributeId = getAttributeCache() .getAttribute(NuclosEOField.STATE.getMetaData().getId().intValue()).getId(); return findAttributeByGoAndAttributeId(iGenericObjectId, iAttributeId).getValueId(); } /** * get all generic objects of a given module related to a given generic object * always moves two steps through the relation hierarchy. * only by doing so ie related assets from which orders were created can be found * because demands are in between assets and orders most of the time * * @param iModuleId module to search for related generic objects in. If null, an empty set is returned. * @param iGenericObjectId generic object to find related generic objects for. If null, an empty set is returned. * @param direction direction to get related generic objects for * @param relationType * @return Collection<Integer> collection of generic object ids * @postcondition result != null * @postcondition (iModuleId == null) --> result.isEmpty() * @postcondition (iGenericObjectId == null) --> result.isEmpty() */ @RolesAllowed("Login") public Set<Integer> getRelatedGenericObjectIds(final Integer iModuleId, final Integer iGenericObjectId, final RelationDirection direction, final String relationType) { // @todo optimize: the two steps are unnecessary for part-of relationships. 16.09.04 CR final Set<Integer> result = new HashSet<Integer>(); if (iModuleId != null && iGenericObjectId != null) { DbQueryBuilder builder = dataBaseHelper.getDbAccess().getQueryBuilder(); DbQuery<DbTuple> query = builder.createTupleQuery(); DbFrom r = query.from("T_UD_GO_RELATION").alias("r"); DbFrom l = query.from("T_UD_GENERICOBJECT").alias("l"); DbColumnExpression<Integer> genericObject1 = r .baseColumn(direction.isReverse() ? "INTID_T_UD_GO_2" : "INTID_T_UD_GO_1", Integer.class); DbColumnExpression<Integer> genericObject2 = r .baseColumn(direction.isReverse() ? "INTID_T_UD_GO_1" : "INTID_T_UD_GO_2", Integer.class); query.multiselect(genericObject2, l.baseColumn("INTID_T_MD_MODULE", Integer.class)); query.where(builder.and(builder.equal(genericObject1, iGenericObjectId), builder.equal(genericObject2, l.baseColumn("INTID", Integer.class)), builder.equal(r.baseColumn("STRRELATIONTYPE", String.class), relationType))); query.distinct(true); List<DbTuple> result1 = dataBaseHelper.getDbAccess().executeQuery(query); for (DbTuple tuple1 : result1) { final Integer intid1 = tuple1.get(0, Integer.class); if (tuple1.get(1, Integer.class).equals(iModuleId)) { result.add(intid1); } else { // Reuse existing query query.multiselect(genericObject2); query.where(builder.and(builder.equal(genericObject1, intid1), builder.equal(genericObject2, l.baseColumn("INTID", Integer.class)), builder.equal(r.baseColumn("STRRELATIONTYPE", String.class), relationType))); for (DbTuple tuple2 : dataBaseHelper.getDbAccess().executeQuery(query)) { result.add(tuple2.get(0, Integer.class)); } } } assert result != null; assert !(iModuleId == null) || result.isEmpty(); assert !(iGenericObjectId == null) || result.isEmpty(); } return result; } /** * fills the dependants of <code>lowdcvo</code> with the data from the required sub entities. * @param lowdcvo * @param stRequiredSubEntityNames * @precondition stRequiredSubEntityNames != null * @deprecated This method doesn't respect the foreign key field name. Replace with fillDependants(). */ @Deprecated private void _fillDependants(GenericObjectWithDependantsVO lowdcvo, UsageCriteria usage, Set<String> stRequiredSubEntityNames, String customUsage) throws CommonFinderException { helper._fillDependants(lowdcvo, usage, stRequiredSubEntityNames, null, this.getCurrentUserName(), customUsage); } /** * attaches document to any object * @param mdvoDocument master data value object with fields for table t_ud_go_document, has to be filled * with following fields: comment, createdDate, createdUser, file and genericObjectId. * @param mdvoDocument * @return Id of created master data entry * @todo restrict permission - check module id! requires the right to modify documents */ @RolesAllowed("Login") public void attachDocumentToObject(MasterDataVO mdvoDocument) { try { DependantMasterDataMap map = new DependantMasterDataMapImpl(); final String entity = (String) mdvoDocument.getField("entity"); map.addData(entity, DalSupportForMD.getEntityObjectVO(entity, mdvoDocument)); int genericObjectId = ((Integer) mdvoDocument.getField("genericObject")).intValue(); int moduleId = getModuleContainingGenericObject(genericObjectId); helper.createDependants(Modules.getInstance().getEntityNameByModuleId(moduleId), genericObjectId, map, Collections.EMPTY_MAP, null); } catch (CommonFinderException ex) { throw new NuclosFatalException(ex); } catch (CommonCreateException ex) { throw new NuclosFatalException(ex); } } /** * execute a list of rules for the given Object * @param lstRuleVO * @param govo * @param bSaveAfterRuleExecution * @throws CommonBusinessException * @todo restrict permission - check module id! */ @RolesAllowed("ExecuteRulesManually") public void executeBusinessRules(List<RuleVO> lstRuleVO, GenericObjectWithDependantsVO govo, boolean bSaveAfterRuleExecution, String customUsage) throws CommonBusinessException { RuleEngineFacadeLocal ruleFacade = ServerServiceLocator.getInstance() .getFacade(RuleEngineFacadeLocal.class); EventSupportFacadeLocal eventSupportFacade = ServerServiceLocator.getInstance() .getFacade(EventSupportFacadeLocal.class); RuleObjectContainerCVO loccvo = ruleFacade.executeBusinessRules(lstRuleVO, new RuleObjectContainerCVOImpl(Event.USER, govo, govo.getDependants()), false, null); loccvo = eventSupportFacade.fireCustomEventSupport(govo.getModuleId(), lstRuleVO, loccvo, false); if (bSaveAfterRuleExecution) { this.modify(loccvo.getGenericObject(), loccvo.getDependants(true), true, customUsage); } } /** * creates a LogbookEntry */ public void createLogbookEntry(Integer genericObjectId, Integer attributeId, Integer masterdataMetaId, Integer masterdataMetaFieldId, Integer masterdataRecordId, String masterdataAction, Integer oldValueId, Integer oldValueExternalId, String oldValue, Integer newValueId, Integer newValueExternalId, String newValue) { MasterDataVO mdvo = MasterDataWrapper.wrapLogbookVO(new LogbookVO(new NuclosValueObject(), genericObjectId, attributeId, masterdataMetaId, masterdataMetaFieldId, masterdataRecordId, masterdataAction, oldValueId, oldValueExternalId, oldValue, newValueId, newValueExternalId, newValue)); try { getMasterDataFacade().create(NuclosEntity.GENERICOBJECTLOGBOOK.getEntityName(), mdvo, null, null); } catch (NuclosBusinessException ex) { throw new NuclosFatalException(ex); } catch (CommonCreateException ex) { throw new NuclosFatalException(ex); } catch (CommonPermissionException ex) { throw new NuclosFatalException(ex); } } /** * creates a GenericObjectAttribute with the given values * @param genericObjectId * @param attributeId * @param valueId * @param canonicalValue * @return a collection of BadAttributeValueException */ public Collection<BadAttributeValueException> createGenericObjectAttribute(Integer genericObjectId, Integer attributeId, Integer valueId, String canonicalValue, boolean logbookTracking) { final Collection<BadAttributeValueException> badAttributes = new ArrayList<BadAttributeValueException>(); final String field = DalSupportForGO.getEntityFieldFromAttribute(attributeId); final EntityObjectVO eo = DalSupportForGO.getEntityObject(genericObjectId); eo.getFieldIds().put(field, IdUtils.toLongId(valueId)); eo.getFields().put(field, DalSupportForGO.convertFromCanonicalAttributeValue(attributeId, canonicalValue)); eo.flagUpdate(); try { DalSupportForGO.getEntityObjectProcesserForGenericObject(genericObjectId).insertOrUpdate(eo); } catch (DbException dbe) { badAttributes.add(new BadAttributeValueException(-1, genericObjectId, canonicalValue, attributeId, getAttributeCache().getAttribute(attributeId), dbe.getMessage())); } if (logbookTracking) { createLogbookEntry(genericObjectId, attributeId, null, null, null, null, null, null, null, DalSupportForGO.isEntityFieldForeign(attributeId) ? null : valueId, DalSupportForGO.isEntityFieldForeign(attributeId) ? valueId : null, canonicalValue); } return badAttributes; } /** * updates a GenericObjectAttribute */ public void updateGenericObjectAttribute(DynamicAttributeVO vo, Integer genericObjectId, boolean logbookTracking) throws NuclosBusinessException { final EntityObjectVO eo = DalSupportForGO.getEntityObjectProcesserForGenericObject(genericObjectId) .getByPrimaryKey(IdUtils.toLongId(genericObjectId)); final String field = DalSupportForGO.getEntityFieldFromAttribute(vo.getAttributeId()); if (logbookTracking) { helper.createLogBookEntryIfNecessary(eo, null, vo); } eo.getFieldIds().put(field, IdUtils.toLongId(vo.getValueId())); eo.getFields().put(field, vo.getValue()); eo.flagUpdate(); try { NucletDalProvider.getInstance().getEntityObjectProcessor(eo.getEntity()).insertOrUpdate(eo); } catch (DbException e) { throw new NuclosBusinessException(e); } } /** * returns the GenericObjectAttribute matching the given genericObjectId and attributeId * @param genericObjectId * @param attributeId * @return the DynamicAttributeVO matching the given genericObjectId and attributeId */ public DynamicAttributeVO findAttributeByGoAndAttributeId(Integer genericObjectId, Integer attributeId) throws CommonFinderException { EntityObjectVO eo = DalSupportForGO.getEntityObject(genericObjectId); String field = DalSupportForGO.getEntityFieldFromAttribute(attributeId); return DalSupportForGO.getDynamicAttributeVO(eo, field); } private boolean getUsesRuleEngine(String sEntityName, String event) { DbQuery<DbTuple> query = dataBaseHelper.getDbAccess().getQueryBuilder().createTupleQuery(); DbFrom from = query.from("T_MD_RULE_EVENT").alias(SystemFields.BASE_ALIAS); List<DbSelection<?>> columns = new ArrayList<DbSelection<?>>(); columns.add(from.baseColumn("intid", Integer.class).alias("intid")); query.multiselect(columns); List<DbCondition> lstDbCondition = new ArrayList<DbCondition>(); lstDbCondition.add( dataBaseHelper.getDbAccess().getQueryBuilder().equal(from.baseColumn("strmasterdata", String.class), dataBaseHelper.getDbAccess().getQueryBuilder().literal(sEntityName))); lstDbCondition .add(dataBaseHelper.getDbAccess().getQueryBuilder().equal(from.baseColumn("strevent", String.class), dataBaseHelper.getDbAccess().getQueryBuilder().literal(event))); query.where(dataBaseHelper.getDbAccess().getQueryBuilder().and(lstDbCondition.toArray(new DbCondition[0]))); List<DbTuple> usages = dataBaseHelper.getDbAccess().executeQuery(query); return (usages.size() > 0); } private boolean getUsesEventSupports(Integer iEntityId, String sEventSupportType) { DbQuery<DbTuple> query = dataBaseHelper.getDbAccess().getQueryBuilder().createTupleQuery(); DbFrom from = query.from("T_MD_EVENTSUPPORT_ENTITY").alias(SystemFields.BASE_ALIAS); List<DbSelection<?>> columns = new ArrayList<DbSelection<?>>(); columns.add(from.baseColumn("intid", Integer.class).alias("intid")); query.multiselect(columns); List<DbCondition> lstDbCondition = new ArrayList<DbCondition>(); lstDbCondition.add(dataBaseHelper.getDbAccess().getQueryBuilder().equal( from.baseColumn("intid_t_md_entity", Integer.class), dataBaseHelper.getDbAccess().getQueryBuilder().literal(iEntityId))); lstDbCondition.add(dataBaseHelper.getDbAccess().getQueryBuilder().equal( from.baseColumn("streventsupporttype", String.class), dataBaseHelper.getDbAccess().getQueryBuilder().literal(sEventSupportType))); query.where(dataBaseHelper.getDbAccess().getQueryBuilder().and(lstDbCondition.toArray(new DbCondition[0]))); List<DbTuple> usages = dataBaseHelper.getDbAccess().executeQuery(query); return (usages.size() > 0); } }