001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.userdirectory.synchronize; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Optional; 024import java.util.Set; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.commons.lang3.StringUtils; 029import org.apache.commons.lang3.tuple.Triple; 030import org.slf4j.Logger; 031 032import org.ametys.cms.content.references.OutgoingReferencesExtractor; 033import org.ametys.cms.data.ContentSynchronizationResult; 034import org.ametys.cms.repository.Content; 035import org.ametys.cms.repository.ContentQueryHelper; 036import org.ametys.cms.repository.ContentTypeExpression; 037import org.ametys.cms.repository.LanguageExpression; 038import org.ametys.cms.repository.ModifiableContent; 039import org.ametys.cms.repository.WorkflowAwareContent; 040import org.ametys.cms.workflow.AbstractContentWorkflowComponent; 041import org.ametys.cms.workflow.EditContentFunction; 042import org.ametys.core.user.CurrentUserProvider; 043import org.ametys.plugins.contentio.synchronize.impl.SQLSynchronizableContentsCollection; 044import org.ametys.plugins.contentio.synchronize.workflow.EditSynchronizedContentFunction; 045import org.ametys.plugins.repository.AmetysObjectIterable; 046import org.ametys.plugins.repository.AmetysObjectIterator; 047import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder; 048import org.ametys.plugins.repository.data.holder.values.SynchronizationResult; 049import org.ametys.plugins.repository.query.expression.AndExpression; 050import org.ametys.plugins.repository.query.expression.Expression; 051import org.ametys.plugins.repository.query.expression.Expression.Operator; 052import org.ametys.plugins.repository.query.expression.ExpressionContext; 053import org.ametys.plugins.repository.query.expression.StringExpression; 054import org.ametys.plugins.userdirectory.DeleteOrgUnitComponent; 055import org.ametys.plugins.userdirectory.OrganisationChartPageHandler; 056import org.ametys.plugins.userdirectory.UserDirectoryPageHandler; 057import org.ametys.plugins.workflow.AbstractWorkflowComponent; 058import org.ametys.runtime.i18n.I18nizableText; 059import org.ametys.runtime.model.View; 060import org.ametys.runtime.model.type.ModelItemTypeConstants; 061 062import com.opensymphony.workflow.InvalidActionException; 063import com.opensymphony.workflow.WorkflowException; 064 065/** 066 * Synchronizable collection for UD Orgunits 067 */ 068public class SQLSynchronizableUDOrgunitCollection extends SQLSynchronizableContentsCollection 069{ 070 /** The internal data name for orgUnit remote sql id */ 071 public static final String ORGUNIT_REMOTE_ID_INTERNAL_DATA = "orgunit-remote-id"; 072 073 /** The result map key for number of deleted contents */ 074 public static final String RESULT_NB_SYNCHRONIZED_ORGUNITS_RELATIONS = "nbSynchronizedOrgUnitsRelations"; 075 076 private static final String __PARAM_SQL_TABLE_USER = "tableNameUser"; 077 private static final String __PARAM_SQL_ORGUNIT_JOIN_COLUMN_NAME = "orgUnitJoinColumnName"; 078 private static final String __PARAM_LOGIN_USER_ATTRIBUTE_NAME = "loginUser"; 079 private static final String __PARAM_SQL_LOGIN_USER_COLUMN_NAME = "loginColumnName"; 080 private static final String __PARAM_SQL_ROLE_USER_COLUMN_NAME = "roleColumnName"; 081 private static final String __PARAM_SQL_ORGUNIT_REMOTE_ID_COLUMN_NAME = "orgunitRemoteIdColumnName"; 082 private static final String __PARAM_SQL_USER_SORT_COLUMN_NAME = "sortColumnName"; 083 private static final String __PARAM_SQL_USER_SORT_PREVAIL_NAME = "sortPrevail"; 084 085 /** The map which link orgunit with this parent */ 086 protected Map<String, String> _orgUnitParents; 087 088 /** The map which link users (userId and role) to their orgunits */ 089 protected Map<String, Map<String, String>> _usersByOrgUnitId; 090 091 /** The map which link orgunit with sql remote ids */ 092 protected Map<String, String> _orgUnitRemoteIds; 093 094 095 /** Number of updated contents for parent-child org unit relation */ 096 protected Integer _nbSynchronizedOrgUnit; 097 098 /** The sql user search DAO */ 099 protected SQLUserSearchDAO _sqlUserDAO; 100 101 /** The organisation chart page handler */ 102 protected OrganisationChartPageHandler _orgChartPageHandler; 103 104 /** The current user provider */ 105 protected CurrentUserProvider _userProvider; 106 107 /** The OutgoingReferences extractor */ 108 protected OutgoingReferencesExtractor _outgoingReferencesExtractor; 109 110 /** The delete orgUnit component */ 111 protected DeleteOrgUnitComponent _deleteOrgUnitComponent; 112 113 @Override 114 public void service(ServiceManager smanager) throws ServiceException 115 { 116 super.service(smanager); 117 _sqlUserDAO = (SQLUserSearchDAO) smanager.lookup(SQLUserSearchDAO.ROLE); 118 _orgChartPageHandler = (OrganisationChartPageHandler) smanager.lookup(OrganisationChartPageHandler.ROLE); 119 _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 120 _outgoingReferencesExtractor = (OutgoingReferencesExtractor) smanager.lookup(OutgoingReferencesExtractor.ROLE); 121 _deleteOrgUnitComponent = (DeleteOrgUnitComponent) smanager.lookup(DeleteOrgUnitComponent.ROLE); 122 } 123 124 public boolean handleRightAssignmentContext() 125 { 126 return false; 127 } 128 129 /** 130 * Get the name of user SQL table 131 * @return The user SQL table name 132 */ 133 public String getUserTableName() 134 { 135 return (String) getParameterValues().get(__PARAM_SQL_TABLE_USER); 136 } 137 138 /** 139 * Get the name of the orgunit join column name of the user table 140 * @return The name of the orgunit join column name 141 */ 142 public String getOrgunitJoinColumnNameForUser() 143 { 144 return (String) getParameterValues().get(__PARAM_SQL_ORGUNIT_JOIN_COLUMN_NAME); 145 } 146 147 /** 148 * Get the login user attribute name 149 * @return The login user attribute name 150 */ 151 public String getLoginUserAttributeName() 152 { 153 return (String) getParameterValues().get(__PARAM_LOGIN_USER_ATTRIBUTE_NAME); 154 } 155 156 /** 157 * Get the login user column name 158 * @return The login user column name 159 */ 160 public String getLoginUserColumnName() 161 { 162 return (String) getParameterValues().get(__PARAM_SQL_LOGIN_USER_COLUMN_NAME); 163 } 164 165 /** 166 * Get the role user column name 167 * @return The role user column name 168 */ 169 public String getRoleUserColumnName() 170 { 171 return (String) getParameterValues().get(__PARAM_SQL_ROLE_USER_COLUMN_NAME); 172 } 173 174 /** 175 * Get the user sort column name 176 * @return The user sort column name 177 */ 178 public String getUserSortColumnName() 179 { 180 return (String) getParameterValues().get(__PARAM_SQL_USER_SORT_COLUMN_NAME); 181 } 182 183 /** 184 * Get the orgunit remote id column name 185 * @return The orgunit remote id column name 186 */ 187 public String getOrgUnitRemoteIdColumnName() 188 { 189 return (String) getParameterValues().get(__PARAM_SQL_ORGUNIT_REMOTE_ID_COLUMN_NAME); 190 } 191 192 /** 193 * True if the SQL sort for users prevail 194 * @return true if the SQL sort for users prevail 195 */ 196 public boolean isUserSortPrevail() 197 { 198 return Boolean.valueOf((String) getParameterValues().get(__PARAM_SQL_USER_SORT_PREVAIL_NAME)); 199 } 200 201 @Override 202 protected Map<String, Object> _getSearchParameters(Map<String, Object> parameters, int offset, int limit, List<Object> sort, List<String> columns) 203 { 204 // Add the sql column name for the orgunit id. 205 // It's for setting the ametys-internal:orgunit-remote-id and retrieve easily the orgUnit content with this Id 206 String orgUnitIdColumnName = getOrgUnitRemoteIdColumnName(); 207 if (!columns.contains(orgUnitIdColumnName)) 208 { 209 columns.add(orgUnitIdColumnName); 210 } 211 212 return super._getSearchParameters(parameters, offset, limit, sort, columns); 213 } 214 215 @Override 216 protected Map<String, Map<String, Object>> internalSearch(Map<String, Object> searchParameters, int offset, int limit, List<Object> sort, Logger logger) 217 { 218 Map<String, Map<String, Object>> internalSearch = super.internalSearch(searchParameters, offset, limit, sort, logger); 219 220 // Fill _orgUnitRemoteIds and _orgUnitParents maps with search results 221 String orgUnitRemoteIdColumnName = getOrgUnitRemoteIdColumnName(); 222 for (String orgUnitIdValue : internalSearch.keySet()) 223 { 224 Map<String, Object> orgUnitValues = internalSearch.get(orgUnitIdValue); 225 _orgUnitRemoteIds.put(orgUnitIdValue, orgUnitValues.get(orgUnitRemoteIdColumnName).toString()); 226 227 Map<String, List<String>> mapping = getMapping(); 228 if (mapping.containsKey(OrganisationChartPageHandler.PARENT_ORGUNIT_ATTRIBUTE_NAME)) 229 { 230 // We take the first because it's no sense to defined two sql columns to define orgunit parents 231 String parentColumn = mapping.get(OrganisationChartPageHandler.PARENT_ORGUNIT_ATTRIBUTE_NAME).get(0); 232 if (orgUnitValues.containsKey(parentColumn)) 233 { 234 String parentId = Optional.of(orgUnitValues) 235 .map(v -> v.get(parentColumn)) 236 .map(Object::toString) 237 .orElse(null); 238 _orgUnitParents.put(orgUnitIdValue, parentId); 239 } 240 } 241 } 242 243 return internalSearch; 244 } 245 246 @Override 247 protected void _logSynchronizationResult(Logger logger) 248 { 249 super._logSynchronizationResult(logger); 250 logger.info("{} contents have been modified to update the parent-child relations.", _nbSynchronizedOrgUnit); 251 } 252 253 @Override 254 protected boolean _hasSomethingChanged() 255 { 256 return super._hasSomethingChanged() || _nbSynchronizedOrgUnit > 0; 257 } 258 259 @Override 260 protected List<ModifiableContent> _internalPopulate(Logger logger) 261 { 262 _orgUnitParents = new HashMap<>(); 263 _orgUnitRemoteIds = new HashMap<>(); 264 _usersByOrgUnitId = _getUsersByOrgUnit(logger); 265 _nbSynchronizedOrgUnit = 0; 266 267 List<ModifiableContent> contents = super._internalPopulate(logger); 268 269 // All orgunits are imported, now we can set relation with parent orgunit 270 _setContentsRelationWithParentOrgunit(contents, logger); 271 272 return contents; 273 } 274 275 /** 276 * Retrieves the user attributes for all org units 277 * @param logger The logger 278 * @return the org units' users 279 */ 280 protected Map<String, Map<String, String>> _getUsersByOrgUnit(Logger logger) 281 { 282 Map<String, Map<String, String>> orgUnitsUsers = new HashMap<>(); 283 284 Map<String, List<String>> mapping = getMapping(); 285 String idField = getIdField(); 286 List<String> orgUnitKeys = mapping.get(idField); 287 if (orgUnitKeys != null && orgUnitKeys.size() > 0) 288 { 289 String orgUnitKey = orgUnitKeys.get(0); 290 Map<String, Object> userParameters = _getSearchUserParameters(orgUnitKey, logger); 291 List<Map<String, Object>> searchUserList = _sqlUserDAO.searchUser(userParameters, getDataSourceId()); 292 293 String loginColumnName = getLoginUserColumnName(); 294 String roleColumnName = getRoleUserColumnName(); 295 296 List<String> userColumns = new ArrayList<>(); 297 userColumns.add(loginColumnName); 298 userColumns.add(orgUnitKey); 299 if (StringUtils.isNotBlank(roleColumnName)) 300 { 301 userColumns.add(roleColumnName); 302 } 303 304 for (Map<String, Object> userMap : searchUserList) 305 { 306 Map<String, Object> normalizedUserMap = _getNormalizedSearchResult(userColumns, userMap); 307 Optional<Triple<String, String, String>> orgUnitUser = _getUserByOrgUnit(orgUnitKey, loginColumnName, roleColumnName, normalizedUserMap, logger); 308 if (orgUnitUser.isPresent()) 309 { 310 Triple<String, String, String> triple = orgUnitUser.get(); 311 String orgUnitId = triple.getLeft(); 312 Map<String, String> orgUnitUsers = orgUnitsUsers.computeIfAbsent(orgUnitId, __ -> new LinkedHashMap<>()); 313 orgUnitUsers.put(triple.getMiddle(), triple.getRight()); 314 } 315 } 316 } 317 318 return orgUnitsUsers; 319 } 320 321 /** 322 * Retrieves a {@link Triple} containing the orgunit id, and the user's login and role for the given normalized user 323 * @param orgUnitKey the orgUnit key 324 * @param loginColumnName the login column name 325 * @param roleColumnName the role column name 326 * @param normalizedUser the normalized user 327 * @param logger the logger 328 * @return the user info as a {@link Triple} 329 */ 330 protected Optional<Triple<String, String, String>> _getUserByOrgUnit(String orgUnitKey, String loginColumnName, String roleColumnName, Map<String, Object> normalizedUser, Logger logger) 331 { 332 String loginValue = (normalizedUser.get(loginColumnName) == null) ? null : String.valueOf(normalizedUser.get(loginColumnName)); 333 String orgUnitIdValue = normalizedUser.get(orgUnitKey).toString(); 334 335 if (StringUtils.isNotBlank(loginValue)) 336 { 337 String roleValue = null; 338 if (StringUtils.isNotBlank(roleColumnName)) 339 { 340 roleValue = (normalizedUser.get(roleColumnName) == null) ? null : String.valueOf(normalizedUser.get(roleColumnName)); 341 } 342 343 return Optional.of(Triple.of(orgUnitIdValue, loginValue, roleValue)); 344 } 345 else 346 { 347 logger.warn("Can't add user to orgunit '" + orgUnitIdValue + "' because the login value is blank ..."); 348 return Optional.empty(); 349 } 350 } 351 352 @Override 353 protected Optional<ModifiableContent> _importOrSynchronizeContent(String idValue, String lang, Map<String, List<Object>> remoteValues, boolean forceImport, Logger logger) 354 { 355 // Do not set relation with parent orgunit now, while they might miss some that are not yet created 356 remoteValues.remove(OrganisationChartPageHandler.PARENT_ORGUNIT_ATTRIBUTE_NAME); 357 358 return super._importOrSynchronizeContent(idValue, lang, remoteValues, forceImport, logger); 359 } 360 361 @Override 362 public ContentSynchronizationResult additionalCommonOperations(ModifiableContent content, Map<String, Object> additionalParameters, Logger logger) 363 { 364 ContentSynchronizationResult result = super.additionalCommonOperations(content, additionalParameters, logger); 365 366 try 367 { 368 SynchronizationResult additionalResult = new SynchronizationResult(); 369 String orgUnitIdValue = content.getValue(getIdField()); 370 ModifiableModelLessDataHolder internalDataHolder = content.getInternalDataHolder(); 371 372 String oldValue = internalDataHolder.getValueOfType(ORGUNIT_REMOTE_ID_INTERNAL_DATA, ModelItemTypeConstants.STRING_TYPE_ID); 373 String value = _orgUnitRemoteIds.get(orgUnitIdValue); 374 375 if (!value.equals(oldValue)) 376 { 377 internalDataHolder.setValue(ORGUNIT_REMOTE_ID_INTERNAL_DATA, value); 378 additionalResult.setHasChanged(true); 379 } 380 381 result.aggregateResult(additionalResult); 382 } 383 catch (Exception e) 384 { 385 _nbError++; 386 logger.error("An error occurred while importing or synchronizing orgunit '{}' and setting its remote id.", content, e); 387 } 388 389 return result; 390 } 391 392 @Override 393 protected Map<String, Object> getAdditionalAttributeValues(String idValue, Content content, Map<String, Object> additionalParameters, boolean create, Logger logger) 394 { 395 Map<String, Object> additionalRemoteValues = super.getAdditionalAttributeValues(idValue, content, additionalParameters, create, logger); 396 397 List<Map<String, Object>> orgUnitUsers = _getOrgUnitUsers(idValue, content.getLanguage()); 398 if (!orgUnitUsers.isEmpty()) 399 { 400 additionalRemoteValues.put(OrganisationChartPageHandler.ORGUNIT_USERS_ATTRIBUTE_NAME, orgUnitUsers); 401 } 402 403 return additionalRemoteValues; 404 } 405 406 /** 407 * Retrieves the users of the given orgunit 408 * @param orgUnitId the orgunit identifier 409 * @param lang the language of the orgunit 410 * @return the users linked to the given orgunit 411 */ 412 protected List<Map<String, Object>> _getOrgUnitUsers(String orgUnitId, String lang) 413 { 414 if (_usersByOrgUnitId.containsKey(orgUnitId)) 415 { 416 List<Map<String, Object>> users = new ArrayList<>(); 417 for (Map.Entry<String, String> user : _usersByOrgUnitId.get(orgUnitId).entrySet()) 418 { 419 Map<String, Object> orgUnitUser = new HashMap<>(); 420 421 String loginValue = user.getKey(); 422 Content userContent = _getUserContent(loginValue, lang); 423 424 if (userContent != null) 425 { 426 String roleValue = user.getValue(); 427 orgUnitUser.put(OrganisationChartPageHandler.ORGUNIT_USER_ROLE_ATTRIBUTE_NAME, roleValue); 428 orgUnitUser.put(OrganisationChartPageHandler.ORGUNIT_USER_ATTRIBUTE_NAME, userContent); 429 430 users.add(orgUnitUser); 431 } 432 } 433 434 return users; 435 } 436 else 437 { 438 return List.of(); 439 } 440 } 441 442 /** 443 * Set all orgunit parents relation for each synchronized content 444 * @param orgUnitContents the synchronized content 445 * @param logger the logger 446 */ 447 protected void _setContentsRelationWithParentOrgunit(List<ModifiableContent> orgUnitContents, Logger logger) 448 { 449 for (ModifiableContent orgUnitContent : orgUnitContents) 450 { 451 try 452 { 453 if (orgUnitContent instanceof WorkflowAwareContent) 454 { 455 I18nizableText commentText = new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_WORKFLOW_ACTION_EDIT_ORGUNIT_REFERENCE_MSG"); 456 String comment = _i18nUtils.translate(commentText, orgUnitContent.getLanguage()); 457 458 View view = View.of(orgUnitContent.getModel(), OrganisationChartPageHandler.PARENT_ORGUNIT_ATTRIBUTE_NAME); 459 460 Map<String, Object> values = new HashMap<>(); 461 String orgUnitIdValue = orgUnitContent.getValue(getIdField()); 462 String newParentSynchroId = _orgUnitParents.get(orgUnitIdValue); 463 Content newParentContent = newParentSynchroId != null ? _getOrgUnitContentFromRemoteId(newParentSynchroId, orgUnitContent.getLanguage(), logger) : null; 464 values.put(OrganisationChartPageHandler.PARENT_ORGUNIT_ATTRIBUTE_NAME, newParentContent); 465 466 Map<String, Object> inputs = new HashMap<>(); 467 if (StringUtils.isNotEmpty(comment)) 468 { 469 inputs.put("comment", comment); 470 } 471 472 Map<String, Object> parameters = new HashMap<>(); 473 474 parameters.put(EditContentFunction.VIEW, view); 475 parameters.put(EditContentFunction.VALUES_KEY, values); 476 parameters.put(EditContentFunction.QUIT, true); 477 inputs.put(AbstractWorkflowComponent.CONTEXT_PARAMETERS_KEY, parameters); 478 479 inputs.put(EditSynchronizedContentFunction.SYNCHRO_INVERT_EDIT_ACTION_ID_KEY, getSynchronizeActionId()); 480 481 Map<String, Object> actionResult = _contentWorkflowHelper.doAction((WorkflowAwareContent) orgUnitContent, getSynchronizeActionId(), inputs); 482 if ((boolean) actionResult.getOrDefault(AbstractContentWorkflowComponent.HAS_CHANGED_KEY, false)) 483 { 484 _nbSynchronizedOrgUnit++; 485 } 486 } 487 } 488 catch (WorkflowException | InvalidActionException e) 489 { 490 logger.error("An error occurred while updating parent-child relations of org unit {} ", orgUnitContent, e); 491 } 492 } 493 } 494 495 /** 496 * Get user content from login value 497 * @param loginValue the login value 498 * @param lang the language 499 * @return the user content 500 */ 501 protected Content _getUserContent(String loginValue, String lang) 502 { 503 String loginAttribute = getLoginUserAttributeName(); 504 Set<String> contentTypes = _contentTypeEP.getSubTypes(UserDirectoryPageHandler.ABSTRACT_USER_CONTENT_TYPE); 505 506 Expression ctypeExpression = new ContentTypeExpression(Operator.EQ, contentTypes.toArray(new String[contentTypes.size()])); 507 LanguageExpression languageExpression = new LanguageExpression(Operator.EQ, lang); 508 StringExpression loginExp = new StringExpression(loginAttribute, Operator.EQ, loginValue); 509 510 Expression userExp = new AndExpression(loginExp, ctypeExpression, languageExpression); 511 String xPathQuery = ContentQueryHelper.getContentXPathQuery(userExp); 512 513 AmetysObjectIterable<Content> contentQuery = _resolver.query(xPathQuery); 514 AmetysObjectIterator<Content> contentIterator = contentQuery.iterator(); 515 if (contentIterator.hasNext()) 516 { 517 return contentIterator.next(); 518 } 519 520 return null; 521 } 522 523 /** 524 * Get orgunit content from the remote Id 525 * @param remoteId the remote Id 526 * @param lang the language 527 * @param logger the logger 528 * @return the orgunit content 529 */ 530 protected Content _getOrgUnitContentFromRemoteId(String remoteId, String lang, Logger logger) 531 { 532 Expression ctypeExpression = new ContentTypeExpression(Operator.EQ, OrganisationChartPageHandler.ORGUNIT_CONTENT_TYPE); 533 StringExpression remoteIdOrgunitExpression = new StringExpression(ORGUNIT_REMOTE_ID_INTERNAL_DATA, Operator.EQ, remoteId, ExpressionContext.newInstance().withInternal(true)); 534 LanguageExpression languageExpression = new LanguageExpression(Operator.EQ, lang); 535 536 Expression collectionExpression = _sccHelper.getCollectionExpression(getId()); 537 538 Expression userExp = new AndExpression(remoteIdOrgunitExpression, ctypeExpression, languageExpression, collectionExpression); 539 String xPathQuery = ContentQueryHelper.getContentXPathQuery(userExp); 540 541 AmetysObjectIterable<Content> contentQuery = _resolver.query(xPathQuery); 542 AmetysObjectIterator<Content> contentIterator = contentQuery.iterator(); 543 if (contentIterator.hasNext()) 544 { 545 return contentIterator.next(); 546 } 547 548 return null; 549 } 550 551 /** 552 * Get the parameters map for user mybatis search 553 * @param orgUnitColumnKey the column name of the orgunit key 554 * @param logger the logger 555 * @return the parameter map 556 */ 557 protected Map<String, Object> _getSearchUserParameters(String orgUnitColumnKey, Logger logger) 558 { 559 Map<String, Object> params = new HashMap<>(); 560 params.put("loginColumnName", getLoginUserColumnName()); 561 params.put("tableUser", getUserTableName()); 562 params.put("tableOrgUnit", getTableName()); 563 params.put("joinColumnName", getOrgunitJoinColumnNameForUser()); 564 params.put("orgUnitColumnKey", orgUnitColumnKey); 565 params.put("orgUnitIdColumnName", getOrgUnitRemoteIdColumnName()); 566 567 String roleUserColumnName = getRoleUserColumnName(); 568 if (StringUtils.isNotBlank(roleUserColumnName)) 569 { 570 params.put("roleColumnName", roleUserColumnName); 571 } 572 573 String sortColumnName = getUserSortColumnName(); 574 if (StringUtils.isNotBlank(sortColumnName)) 575 { 576 params.put("sortColumnName", sortColumnName); 577 } 578 579 return params; 580 } 581 582 @Override 583 protected int _deleteContents(List<Content> contentsToRemove, Logger logger) 584 { 585 return _deleteOrgUnitComponent.deleteContentsWithLog(contentsToRemove, Map.of(DeleteOrgUnitComponent.SCC_ID_PARAMETERS_KEY, getId()), Map.of(), logger); 586 } 587 588 @Override 589 public Map<String, Integer> getSynchronizationResult() 590 { 591 Map<String, Integer> result = super.getSynchronizationResult(); 592 593 result.put(RESULT_NB_SYNCHRONIZED_ORGUNITS_RELATIONS, _nbSynchronizedOrgUnit); 594 595 return result; 596 } 597}