From e975f1635bb4679fe5a549c494105ff0b2c681fc Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 23 Oct 2015 14:38:31 +0200 Subject: [PATCH 001/116] Interim commit: minor changes. --- .../midpoint/certification/impl/AccCertUpdateHelper.java | 8 ++++---- .../certification/impl/CertificationManagerImpl.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java index 648d6d5f382..40822b9655a 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java @@ -216,7 +216,7 @@ void closeCampaign(AccessCertificationCampaignType campaign, Task task, Operatio repositoryService.modifyObject(AccessCertificationCampaignType.class, campaign.getOid(), Arrays.asList(stateDelta, stageNumberDelta, triggerDelta), result); - AccessCertificationCampaignType updatedCampaign = updateCampaign(campaign, task, result); + AccessCertificationCampaignType updatedCampaign = refreshCampaign(campaign, task, result); // if (currentState == IN_REMEDIATION) { // eventHelper.onCampaignStageEnd(updatedCampaign, task, result); // } @@ -224,7 +224,7 @@ void closeCampaign(AccessCertificationCampaignType campaign, Task task, Operatio } // TODO implement more efficiently - public AccessCertificationCampaignType updateCampaign(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException { + public AccessCertificationCampaignType refreshCampaign(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException { return repositoryService.getObject(AccessCertificationCampaignType.class, campaign.getOid(), null, result).asObjectable(); } @@ -523,7 +523,7 @@ void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCerti repositoryService.modifyObject(AccessCertificationCampaignType.class, campaign.getOid(), itemDeltaList, result); // notifications - campaign = updateCampaign(campaign, task, result); + campaign = refreshCampaign(campaign, task, result); if (campaign.getCurrentStageNumber() == 1) { eventHelper.onCampaignStart(campaign, task, result); } @@ -544,7 +544,7 @@ void recordCloseCurrentState(AccessCertificationCampaignType campaign, Task task campaignDeltaList.add(triggerDelta); repositoryService.modifyObject(AccessCertificationCampaignType.class, campaign.getOid(), campaignDeltaList, result); - campaign = updateCampaign(campaign, task, result); + campaign = refreshCampaign(campaign, task, result); eventHelper.onCampaignStageEnd(campaign, task, result); } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java index 26273b0bafb..00a9bd07483 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java @@ -279,7 +279,7 @@ public void startRemediation(String campaignOid, Task task, OperationResult pare } updateHelper.setStageNumberAndState(campaign, lastStageNumber + 1, IN_REMEDIATION, task, result); - campaign = updateHelper.updateCampaign(campaign, task, result); + campaign = updateHelper.refreshCampaign(campaign, task, result); eventHelper.onCampaignStageStart(campaign, task, result); } } catch (RuntimeException e) { From 8ed81ccc272bb7e73ebc327d4b0abe3b7d8e4b5f Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 2 Nov 2015 16:53:23 +0100 Subject: [PATCH 002/116] Repository hibernate query diagnostic window + Implemented security for org closure check. --- .../evolveum/midpoint/web/page/PageBase.java | 5 + .../page/admin/configuration/PageAbout.java | 14 +- .../admin/configuration/PageRepoQuery.html | 41 ++++++ .../admin/configuration/PageRepoQuery.java | 120 ++++++++++++++++++ .../admin/configuration/dto/RepoQueryDto.java | 47 +++++++ .../localization/Midpoint.properties | 4 + .../model/api/ModelDiagnosticService.java | 9 +- .../impl/controller/ModelDiagController.java | 40 +++++- .../midpoint/repo/api/RepositoryService.java | 12 ++ .../midpoint/repo/cache/RepositoryCache.java | 5 + .../repo/sql/SqlRepositoryServiceImpl.java | 76 +++++++++++ .../data/common/container/RAssignment.java | 11 ++ .../data/common/other/RLookupTableRow.java | 12 ++ 13 files changed, 385 insertions(+), 11 deletions(-) create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.html create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.java create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/RepoQueryDto.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java index b341c21b5ac..0adda1ed51d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java @@ -486,6 +486,11 @@ private MainMenuItem createConfigurationItems() { menu = new MenuItem(createStringResource("PageAdmin.menu.top.configuration.repositoryObjectView"), PageDebugView.class, null, createVisibleDisabledBehaviorForEditMenu(PageDebugView.class)); submenu.add(menu); + if (SystemConfigurationHolder.isExperimentalCodeEnabled()) { + menu = new MenuItem(createStringResource("PageAdmin.menu.top.configuration.repoQuery"), + PageRepoQuery.class); + submenu.add(menu); + } PageParameters params = new PageParameters(); params.add(PageSystemConfiguration.SELECTED_TAB_INDEX, PageSystemConfiguration.CONFIGURATION_TAB_BASIC); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageAbout.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageAbout.java index 138e18a58d9..65a2e731321 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageAbout.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageAbout.java @@ -22,6 +22,8 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -299,9 +301,15 @@ private void testRepositoryPerformed(AjaxRequestTarget target) { } private void testRepositoryCheckOrgClosurePerformed(AjaxRequestTarget target) { - Task task = createSimpleTask(OPERATION_TEST_REPOSITORY_CHECK_ORG_CLOSURE); - - OperationResult result = getModelDiagnosticService().repositoryTestOrgClosureConsistency(task, true); + OperationResult result = new OperationResult(OPERATION_GET_PROVISIONING_DIAG); + try { + Task task = createSimpleTask(OPERATION_TEST_REPOSITORY_CHECK_ORG_CLOSURE); + getModelDiagnosticService().repositoryTestOrgClosureConsistency(task, true, result); + } catch (SchemaException|SecurityViolationException e) { + result.recordFatalError(e); + } finally { + result.computeStatusIfUnknown(); + } showResult(result); target.add(getFeedbackPanel()); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.html new file mode 100644 index 00000000000..e4b30364f9f --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.html @@ -0,0 +1,41 @@ + + + + + + +
+
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+ + +
+ + \ No newline at end of file diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.java new file mode 100644 index 00000000000..b8f6f2ec20c --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepoQuery.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.web.page.admin.configuration; + +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.application.AuthorizationAction; +import com.evolveum.midpoint.web.application.PageDescriptor; +import com.evolveum.midpoint.web.component.AceEditor; +import com.evolveum.midpoint.web.component.AjaxSubmitButton; +import com.evolveum.midpoint.web.page.admin.configuration.dto.RepoQueryDto; +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.TextArea; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; + +/** + * @author lazyman + * @author mederly + */ +@PageDescriptor(url = "/admin/config/repoQuery", action = { + @AuthorizationAction(actionUri = PageAdminConfiguration.AUTH_CONFIGURATION_ALL, + label = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_LABEL, description = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_DESCRIPTION) +}) +public class PageRepoQuery extends PageAdminConfiguration { + + private static final Trace LOGGER = TraceManager.getTrace(PageRepoQuery.class); + + private static final String DOT_CLASS = PageRepoQuery.class.getName() + "."; + private static final String OPERATION_PERFORM_QUERY = "performQuery"; + + private static final String ID_MAIN_FORM = "mainForm"; + private static final String ID_EXECUTE = "execute"; + private static final String ID_EDITOR = "editor"; + private static final String ID_ANSWER = "answer"; + + private IModel model = new Model<>(new RepoQueryDto()); + + public PageRepoQuery() { + initLayout(); + } + + private void initLayout() { + Form mainForm = new Form(ID_MAIN_FORM); + add(mainForm); + + AceEditor editor = new AceEditor(ID_EDITOR, new PropertyModel(model, RepoQueryDto.F_QUERY)); + mainForm.add(editor); + + AjaxSubmitButton start = new AjaxSubmitButton(ID_EXECUTE, createStringResource("PageRepoQuery.button.execute")) { + + @Override + protected void onError(AjaxRequestTarget target, Form form) { + target.add(getFeedbackPanel()); + } + + @Override + protected void onSubmit(AjaxRequestTarget target, Form form) { + queryPerformed(target); + } + }; + mainForm.add(start); + + TextArea answer = new TextArea(ID_ANSWER, new PropertyModel(model, RepoQueryDto.F_ANSWER)); + answer.setOutputMarkupId(true); + answer.setEnabled(false); + mainForm.add(answer); + } + + private void queryPerformed(AjaxRequestTarget target) { + Task task = createSimpleTask(OPERATION_PERFORM_QUERY); + OperationResult result = new OperationResult(OPERATION_PERFORM_QUERY); + + RepoQueryDto repoQueryDto = model.getObject(); + + String query = repoQueryDto.getQuery(); + if(StringUtils.isEmpty(query)){ + warn(getString("PageRepoQuery.message.emptyString")); + target.add(getFeedbackPanel()); + return; + } + + try { + String answer = getModelDiagnosticService().executeRepositoryQuery(query, task, result); + repoQueryDto.setAnswer(answer); + } catch (SecurityViolationException|SchemaException|RuntimeException e) { + result.recordFatalError("Couldn't execute query", e); + LoggingUtils.logException(LOGGER, "Couldn't execute query", e); + repoQueryDto.setAnswer(e.toString()); + } finally { + result.computeStatus(); + } + + showResult(result); + target.add(getFeedbackPanel()); + target.add(get(createComponentPath(ID_MAIN_FORM, ID_ANSWER))); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/RepoQueryDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/RepoQueryDto.java new file mode 100644 index 00000000000..6f6bfbcf92f --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/RepoQueryDto.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.web.page.admin.configuration.dto; + +import java.io.Serializable; + +/** + * @author mederly + */ +public class RepoQueryDto implements Serializable { + + public static final String F_QUERY = "query"; + public static final String F_ANSWER = "answer"; + + private String query; + private String answer; + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } +} diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index e449981f916..9a36b94e17d 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -1057,6 +1057,7 @@ PageAdmin.menu.top.certification.newDefinition=New campaign definition PageAdmin.menu.top.configuration.about=About PageAdmin.menu.top.configuration.basic=System PageAdmin.menu.top.configuration.bulkActions=Bulk actions +PageAdmin.menu.top.configuration.repoQuery=Repository query PageAdmin.menu.top.configuration=Configuration PageAdmin.menu.top.configuration.configuration=Configuration PageAdmin.menu.top.configuration.development=Development @@ -1183,6 +1184,9 @@ PageBulkAction.button.start=Start PageBulkAction.message.emptyString=Inserted bulk action is empty. Please provide non-empty script. PageBulkAction.options=Options PageBulkAction.title=User bulk actions +PageRepoQuery.title=Repository query (Hibernate) +PageRepoQuery.button.execute=Execute query +PageRepoQuery.message.emptyString=Entered query string is empty. Please provide non-empty query string. PageCert.ago={0} ago PageCertCampaign.basic=Basic PageCertCampaign.button.back=Back diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelDiagnosticService.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelDiagnosticService.java index a549a2e196f..179d818f041 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelDiagnosticService.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelDiagnosticService.java @@ -48,6 +48,7 @@ public interface ModelDiagnosticService { String CLASS_NAME_WITH_DOT = ModelDiagnosticService.class.getName() + "."; String REPOSITORY_SELF_TEST = CLASS_NAME_WITH_DOT + "repositorySelfTest"; String REPOSITORY_TEST_ORG_CLOSURE_CONSISTENCY = CLASS_NAME_WITH_DOT + "repositoryTestOrgClosureConsistency"; + String REPOSITORY_EXECUTE_QUERY = CLASS_NAME_WITH_DOT + "repositoryExecuteQuery"; String PROVISIONING_SELF_TEST = CLASS_NAME_WITH_DOT + "provisioningSelfTest"; /** @@ -76,7 +77,7 @@ public interface ModelDiagnosticService { * * TODO this method is SQL service specific; it should be generalized/fixed somehow. */ - public OperationResult repositoryTestOrgClosureConsistency(Task task, boolean repairIfNecessary); + public void repositoryTestOrgClosureConsistency(Task task, boolean repairIfNecessary, OperationResult result) throws SchemaException, SecurityViolationException; /** * Runs a short, non-destructive internal provisioning test. It tests provisioning framework and @@ -89,4 +90,10 @@ public interface ModelDiagnosticService { */ public ProvisioningDiag getProvisioningDiag(Task task, OperationResult parentResult); + /** + * Execute arbitrary implementation-specific query. In current implementation this means hibernate query. + * + * EXPERIMENTAL. + */ + public String executeRepositoryQuery(String query, Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java index 9e8c1541051..3a5ceaf9a3e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java @@ -21,6 +21,9 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.schema.ProvisioningDiag; +import com.evolveum.midpoint.security.api.AuthorizationConstants; +import com.evolveum.midpoint.security.api.SecurityEnforcer; +import com.evolveum.midpoint.util.exception.SecurityViolationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -30,7 +33,6 @@ import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; @@ -85,6 +87,9 @@ public class ModelDiagController implements ModelDiagnosticService { @Autowired(required = true) private ProvisioningService provisioningService; + + @Autowired + private SecurityEnforcer securityEnforcer; private RandomString randomString; @@ -116,14 +121,35 @@ public OperationResult repositorySelfTest(Task task) { } @Override - public OperationResult repositoryTestOrgClosureConsistency(Task task, boolean repairIfNecessary) { - OperationResult testResult = new OperationResult(REPOSITORY_TEST_ORG_CLOSURE_CONSISTENCY); - repositoryService.testOrgClosureConsistency(repairIfNecessary, testResult); - testResult.computeStatus(); - return testResult; + public void repositoryTestOrgClosureConsistency(Task task, boolean repairIfNecessary, OperationResult parentResult) throws SchemaException, SecurityViolationException { + OperationResult result = parentResult.createSubresult(REPOSITORY_TEST_ORG_CLOSURE_CONSISTENCY); + try { + securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result); // only admin can do this + repositoryService.testOrgClosureConsistency(repairIfNecessary, result); + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } } - @Override + @Override + public String executeRepositoryQuery(String query, Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException { + OperationResult result = parentResult.createSubresult(REPOSITORY_EXECUTE_QUERY); + try { + securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result); // only admin can do this + String answer = repositoryService.executeArbitraryQuery(query, result); + return answer; + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } + } + + @Override public OperationResult provisioningSelfTest(Task task) { OperationResult testResult = new OperationResult(PROVISIONING_SELF_TEST); // Give provisioning chance to run its own self-test diff --git a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java index 7ba40eba4f4..bc143502a81 100644 --- a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java +++ b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java @@ -146,6 +146,7 @@ public interface RepositoryService { String SEARCH_SHADOW_OWNER = CLASS_NAME_WITH_DOT + "searchShadowOwner"; String ADVANCE_SEQUENCE = CLASS_NAME_WITH_DOT + "advanceSequence"; String RETURN_UNUSED_VALUES_TO_SEQUENCE = CLASS_NAME_WITH_DOT + "returnUnusedValuesToSequence"; + String EXECUTE_ARBITRARY_QUERY = CLASS_NAME_WITH_DOT + "executeArbitraryQuery"; /** * Returns object for provided OID. @@ -540,4 +541,15 @@ List> listResourceObjectShadows(String res * TODO this method is SQL service specific; it should be generalized/fixed somehow. */ void testOrgClosureConsistency(boolean repairIfNecessary, OperationResult testResult); + + /** + * A bit of hack - execute arbitrary query, e.g. hibernate query in case of SQL repository. + * Use with all the care! + * + * @param query + * @param result + * @return + */ + String executeArbitraryQuery(String query, OperationResult result); + } diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java index 1128a528639..fe4aa0de40a 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java @@ -381,4 +381,9 @@ public void returnUnusedValuesToSequence(String oid, Collection unusedValu invalidateCacheEntry(SequenceType.class, oid); } } + + @Override + public String executeArbitraryQuery(String query, OperationResult result) { + return repository.executeArbitraryQuery(query, result); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index a27a04561cb..e095464e603 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -2375,4 +2375,80 @@ private void returnUnusedValuesToSequenceAttempt(String oid, Collection un } } + @Override + public String executeArbitraryQuery(String query, OperationResult result) { + Validate.notEmpty(query, "Query must not be empty."); + Validate.notNull(result, "Operation result must not be null."); + + LOGGER.debug("Executing arbitrary query '{}'.", query); + + final String operation = "querying"; + int attempt = 1; + + OperationResult subResult = result.createMinorSubresult(EXECUTE_ARBITRARY_QUERY); + subResult.addParam("query", query); + + SqlPerformanceMonitor pm = getPerformanceMonitor(); + long opHandle = pm.registerOperationStart("executeArbitraryQuery"); + + try { + while (true) { + try { + return executeArbitraryQueryAttempt(query, subResult); + } catch (RuntimeException ex) { + attempt = logOperationAttempt(null, operation, attempt, ex, subResult); + pm.registerOperationNewTrial(opHandle, attempt); + } + } + } finally { + pm.registerOperationFinish(opHandle, attempt); + } + } + + private String executeArbitraryQueryAttempt(String queryString, OperationResult result) { + LOGGER_PERFORMANCE.debug("> execute query {}", queryString); + + Session session = null; + StringBuffer answer = new StringBuffer(); + try { + session = beginReadOnlyTransaction(); // beware, not all databases support read-only transactions! + + Query query = session.createQuery(queryString); + List results = query.list(); + if (results != null) { + answer.append("Result: ").append(results.size()).append(" item(s):\n\n"); + for (Object item : results) { + if (item instanceof Object[]) { + boolean first = true; + for (Object item1 : (Object[]) item) { + if (first) { + first = false; + } else { + answer.append(","); + } + answer.append(item1); + } + } else { + answer.append(item); + } + answer.append("\n"); + } + } + session.getTransaction().rollback(); + } catch (RuntimeException ex) { + handleGeneralException(ex, session, result); + } finally { + cleanupSessionAndResult(session, result); + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Executed query:\n{}\nwith result:\n{}", queryString, answer); + } + + return answer.toString(); + } + + + + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java index 2e64f0ae9e7..bcc0b72a127 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java @@ -392,4 +392,15 @@ public static void copyFromJAXB(AssignmentType jaxb, RAssignment repo, ObjectTyp MetadataFactory.fromJAXB(jaxb.getMetadata(), repo, prismContext); } + + @Override + public String toString() { + return "RAssignment{" + + "id=" + id + + ", ownerOid='" + ownerOid + '\'' + + ", owner=" + owner + + ", targetRef=" + targetRef + + ", resourceRef=" + resourceRef + + '}'; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java index e8a8842b956..1015d37d3c1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java @@ -191,4 +191,16 @@ private static RLookupTableRow toRepo(LookupTableRowType row) { return rRow; } + + @Override + public String toString() { + return "RLookupTableRow{" + + "id=" + id + + ", owner=" + owner + + ", ownerOid='" + ownerOid + '\'' + + ", key='" + key + '\'' + + ", value='" + value + '\'' + + ", label=" + label + + '}'; + } } From 406f0bdd0f76000fc3897645c1b09d11699a4793 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 5 Nov 2015 21:54:15 +0100 Subject: [PATCH 003/116] Sample for creating a query via JAXB. --- .../testing/model/client/sample/Main.java | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/samples/model-client-sample/src/main/java/com/evolveum/midpoint/testing/model/client/sample/Main.java b/samples/model-client-sample/src/main/java/com/evolveum/midpoint/testing/model/client/sample/Main.java index 14f4f438ff9..6b6cab195bd 100644 --- a/samples/model-client-sample/src/main/java/com/evolveum/midpoint/testing/model/client/sample/Main.java +++ b/samples/model-client-sample/src/main/java/com/evolveum/midpoint/testing/model/client/sample/Main.java @@ -40,12 +40,15 @@ import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelPortType; import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelService; +import com.evolveum.prism.xml.ns._public.query_3.ObjectFactory; import com.evolveum.prism.xml.ns._public.query_3.OrderDirectionType; import com.evolveum.prism.xml.ns._public.query_3.PagingType; +import com.evolveum.prism.xml.ns._public.query_3.PropertyComplexValueFilterClauseType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; +import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; @@ -63,7 +66,9 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; +import javax.xml.transform.dom.DOMResult; import javax.xml.ws.BindingProvider; import javax.xml.ws.Holder; import java.io.BufferedReader; @@ -206,7 +211,7 @@ private static SystemConfigurationType getConfiguration(ModelPortType modelPort) SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); modelPort.getObject(ModelClientUtil.getTypeQName(SystemConfigurationType.class), SystemObjectsType.SYSTEM_CONFIGURATION.value(), options, - objectHolder, resultHolder); + objectHolder, resultHolder); return (SystemConfigurationType) objectHolder.value; } @@ -484,21 +489,54 @@ private static void modifyRoleReplaceInducement(ModelPortType modelPort, String } } + private static QueryType createUserQuery1(String username) throws JAXBException, SAXException, IOException { + // WARNING: in a real case make sure that the username is properly escaped before putting it in XML + SearchFilterType filter = ModelClientUtil.parseSearchFilterType( + "" + + "c:name" + + "" + username + "" + + "" + ); + QueryType query = new QueryType(); + query.setFilter(filter); + return query; + } + + private static QueryType createUserQuery2(String username) throws JAXBException { + QueryType query = new QueryType(); + + SearchFilterType filter = new SearchFilterType(); + + PropertyComplexValueFilterClauseType fc = new PropertyComplexValueFilterClauseType(); + ItemPathType path = new ItemPathType(); + path.setValue("declare namespace c=\"http://midpoint.evolveum.com/xml/ns/public/common/common-3\"; c:name"); + fc.setPath(path); + fc.setValue(username); + + ObjectFactory factory = new ObjectFactory(); + JAXBElement equal = factory.createEqual(fc); + + JAXBContext jaxbContext = JAXBContext.newInstance("com.evolveum.midpoint.xml.ns._public.common.api_types_3:" + + "com.evolveum.midpoint.xml.ns._public.common.common_3:" + + "com.evolveum.prism.xml.ns._public.annotation_3:" + + "com.evolveum.prism.xml.ns._public.query_3:" + + "com.evolveum.prism.xml.ns._public.types_3:"); + Marshaller marshaller = jaxbContext.createMarshaller(); + DOMResult result = new DOMResult(); + marshaller.marshal(equal, result); + filter.setFilterClause(((Document) result.getNode()).getDocumentElement()); + + query.setFilter(filter); + return query; + } + private static UserType searchUserByName(ModelPortType modelPort, String username) throws SAXException, IOException, FaultMessage, JAXBException { - // WARNING: in a real case make sure that the username is properly escaped before putting it in XML - SearchFilterType filter = ModelClientUtil.parseSearchFilterType( - "" + - "c:name" + - "" + username + "" + - "" - ); - QueryType query = new QueryType(); - query.setFilter(filter); + SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder objectListHolder = new Holder(); Holder resultHolder = new Holder(); - modelPort.searchObjects(ModelClientUtil.getTypeQName(UserType.class), query, options, objectListHolder, resultHolder); + modelPort.searchObjects(ModelClientUtil.getTypeQName(UserType.class), createUserQuery1(username), options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; List objects = objectList.getObject(); From a568fbd96f8c0f1b582b57bf480c01e6bff197c4 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 12 Nov 2015 19:36:48 +0100 Subject: [PATCH 004/116] Removed certification cases from campaign object (interim commit). --- .../admin/configuration/PageDebugView.java | 10 +- .../midpoint/schema/SelectorOptions.java | 4 +- .../xml/ns/public/common/common-3.xsd | 2 +- .../repo/sql/SqlRepositoryServiceImpl.java | 145 ++++++++- .../common/RAccessCertificationCampaign.java | 32 ++ .../repo/sql/data/common/RObject.java | 3 + .../container/RAccessCertificationCase.java | 277 ++++++++++++++++++ .../embedded/REmbeddedNamedReference.java | 117 ++++++++ .../midpoint/repo/sql/util/RUtil.java | 11 + 9 files changed, 594 insertions(+), 7 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugView.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugView.java index 6f3ca7b0c58..7d3750c8137 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugView.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugView.java @@ -42,6 +42,7 @@ import com.evolveum.midpoint.web.page.admin.dto.ObjectViewDto; import com.evolveum.midpoint.web.security.MidPointApplication; import com.evolveum.midpoint.web.util.WebMiscUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportType; @@ -137,15 +138,20 @@ private ObjectViewDto loadObject() { type = getPrismContext().getSchemaRegistry().determineCompileTimeClass(new QName(SchemaConstantsGenerated.NS_COMMON, objectType.toString())); } + // TODO make this configurable (or at least do not show campaign cases in production) if (UserType.class.isAssignableFrom(type)) { options.add(SelectorOptions.create(UserType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); } - - if(objectType != null && LookupTableType.COMPLEX_TYPE.getLocalPart().equals(objectType.toString())){ + if (LookupTableType.class.isAssignableFrom(type)) { options.add(SelectorOptions.create(LookupTableType.F_ROW, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); } + if (AccessCertificationCampaignType.class.isAssignableFrom(type)) { + options.add(SelectorOptions.create(AccessCertificationCampaignType.F_CASE, + GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); + } + PrismObject object = getModelService().getObject(type, objectOid.toString(), options, task, result); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java index d354a63d7f2..2dc5be62f65 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java @@ -28,6 +28,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @@ -143,7 +144,8 @@ public static boolean hasToLoadPath(QName itemName, Collection> options) { List> retrieveOptions = filterRetrieveOptions(options); diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index d6b78c3ef10..3a4caca3523 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -12766,8 +12766,8 @@ - + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index e095464e603..12d7673a818 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -39,6 +39,10 @@ import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; +import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; @@ -620,6 +624,7 @@ private String overwriteAddObjectAttempt(PrismObject o updateFullObject(rObject, object); RObject merged = (RObject) session.merge(rObject); addLookupTableRows(session, rObject, modifications != null); + addCertificationCampaignCases(session, rObject, modifications != null); if (getClosureManager().isEnabled()) { OrgClosureManager.Operation operation; @@ -645,6 +650,9 @@ private void updateFullObject(RObject object, PrismObject } else if (LookupTableType.class.equals(savedObject.getCompileTimeClass())) { PrismContainer table = savedObject.findContainer(LookupTableType.F_ROW); savedObject.remove(table); + } else if (AccessCertificationCampaignType.class.equals(savedObject.getCompileTimeClass())) { + PrismContainer caseContainer = savedObject.findContainer(AccessCertificationCampaignType.F_CASE); + savedObject.remove(caseContainer); } String xml = getPrismContext().serializeObjectToString(savedObject, PrismContext.LANG_XML); @@ -682,6 +690,7 @@ private String nonOverwriteAddObjectAttempt(PrismObject modifications = createAddParentRefDelta(object); @@ -763,6 +772,9 @@ private void deleteObjectAttempt(Class type, String oi if (LookupTableType.class.equals(type)) { deleteLookupTableRows(session, oid); } + if (AccessCertificationCampaignType.class.equals(type)) { + deleteCertificationCampaignCases(session, oid); + } session.getTransaction().commit(); } catch (ObjectNotFoundException ex) { @@ -801,6 +813,29 @@ private void addLookupTableRows(Session session, RObject object, boolean merge) } } + private void deleteCertificationCampaignCases(Session session, String oid) { + Query query = session.getNamedQuery("delete.campaignCases"); + query.setParameter("oid", oid); + + query.executeUpdate(); + } + + private void addCertificationCampaignCases(Session session, RObject object, boolean merge) { + if (!(object instanceof RAccessCertificationCampaign)) { + return; + } + RAccessCertificationCampaign campaign = (RAccessCertificationCampaign) object; + + if (merge) { + deleteCertificationCampaignCases(session, campaign.getOid()); + } + if (campaign.getCases() != null) { + for (RAccessCertificationCase aCase : campaign.getCases()) { + session.save(aCase); + } + } + } + private void addLookupTableRows(Session session, String tableOid, Collection values, int currentId) { for (PrismContainerValue value : values) { LookupTableRowType rowType = new LookupTableRowType(); @@ -813,6 +848,18 @@ private void addLookupTableRows(Session session, String tableOid, Collection values, int currentId) { + for (PrismContainerValue value : values) { + AccessCertificationCaseType caseType = new AccessCertificationCaseType(); + caseType.setupContainerValue(value); + + RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, getPrismContext()); + row.setId(currentId); + currentId++; + session.save(row); + } + } + private void updateLookupTableData(Session session, RObject object, Collection modifications) { if (modifications.isEmpty()) { return; @@ -841,7 +888,7 @@ private void updateLookupTableData(Session session, RObject object, Collection modifications) { + if (modifications.isEmpty()) { + return; + } + + if (!(object instanceof RAccessCertificationCampaign)) { + throw new IllegalStateException("Object being modified is not a RAccessCertificationCampaign; it is " + object.getClass()); + } + final RAccessCertificationCampaign rCampaign = (RAccessCertificationCampaign) object; + final String campaignOid = object.getOid(); + + for (ItemDelta delta : modifications) { + if (!(delta instanceof ContainerDelta) || delta.getPath().size() != 1) { + throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + delta.getPath()); + } + // one "case" container modification + ContainerDelta containerDelta = (ContainerDelta) delta; + + if (containerDelta.getValuesToDelete() != null) { + // todo do 'bulk' delete like delete from ... where oid=? and id in (...) + for (PrismContainerValue value : (Collection) containerDelta.getValuesToDelete()) { + Query query = session.getNamedQuery("delete.campaignCase"); + query.setString("oid", campaignOid); + query.setInteger("id", RUtil.toInteger(value.getId())); + query.executeUpdate(); + } + } + if (containerDelta.getValuesToAdd() != null) { + int currentId = findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; + addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToAdd(), currentId); + } + if (containerDelta.getValuesToReplace() != null) { + deleteCertificationCampaignCases(session, campaignOid); + addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToReplace(), 1); + } + } + } + + private int findLastIdInRepo(Session session, String tableOid, String queryName) { + Query query = session.getNamedQuery(queryName); query.setString("oid", tableOid); Integer lastId = (Integer) query.uniqueResult(); if (lastId == null) { @@ -1083,6 +1168,8 @@ private PrismObject updateLoadedObject(GetObjectResult LOGGER.debug("Definitions for attributes loaded. Counts: {}", Arrays.toString(counts)); } else if (LookupTableType.class.equals(prismObject.getCompileTimeClass())) { updateLoadedLookupTable(prismObject, options, session); + } else if (AccessCertificationCampaignType.class.equals(prismObject.getCompileTimeClass())) { + updateLoadedCampaign(prismObject, options, session); } GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); @@ -1216,6 +1303,31 @@ private void updateLoadedLookupTable(PrismObject objec } } + private void updateLoadedCampaign(PrismObject object, + Collection> options, + Session session) throws SchemaException { + if (!SelectorOptions.hasToLoadPath(AccessCertificationCampaignType.F_CASE, options)) { + return; + } + + LOGGER.debug("Loading certification campaign cases."); + + Criteria criteria = session.createCriteria(RAccessCertificationCase.class); + criteria.add(Restrictions.eq("ownerOid", object.getOid())); + + List cases = criteria.list(); + if (cases == null || cases.isEmpty()) { + return; + } + + AccessCertificationCampaignType campaign = (AccessCertificationCampaignType) object.asObjectable(); + List jaxbCases = campaign.getCase(); + for (RAccessCertificationCase rCase : cases) { + AccessCertificationCaseType jaxbCase = rCase.toJAXB(getPrismContext()); + jaxbCases.add(jaxbCase); + } + } + private Criteria setupLookupTableRowsQuery(Session session, RelationalValueSearchQuery queryDef, String oid) { Criteria criteria = session.createCriteria(RLookupTableRow.class); criteria.add(Restrictions.eq("ownerOid", oid)); @@ -1377,6 +1489,7 @@ private void modifyObjectAttempt(Class type, String oi closureContext = getClosureManager().onBeginTransactionModify(session, type, oid, modifications); Collection lookupTableModifications = filterLookupTableModifications(type, modifications); + Collection campaignCaseModifications = filterCampaignCaseModifications(type, modifications); // JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big. // Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo @@ -1427,6 +1540,7 @@ private void modifyObjectAttempt(Class type, String oi session.merge(rObject); updateLookupTableData(session, rObject, lookupTableModifications); + updateCampaignCases(session, rObject, campaignCaseModifications); if (getClosureManager().isEnabled()) { getClosureManager().updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext); @@ -1494,6 +1608,31 @@ private Collection filterLookupTable return tableDelta; } + private Collection filterCampaignCaseModifications(Class type, + Collection modifications) { + Collection caseDelta = new ArrayList<>(); + if (!AccessCertificationCampaignType.class.equals(type)) { + return caseDelta; + } + + ItemPath casePath = new ItemPath(AccessCertificationCampaignType.F_CASE); + for (ItemDelta delta : modifications) { + ItemPath path = delta.getPath(); + if (path.isEmpty()) { + throw new UnsupportedOperationException("Certification campaign cannot be modified via empty-path modification"); + } else if (path.equivalent(casePath)) { + caseDelta.add(delta); + } else if (path.isSuperPath(casePath)) { + // todo - what about modifications with path like case[id] or case[id]/xxx? + throw new UnsupportedOperationException("Campaign case can be modified only by specifying path=case"); + } + } + + modifications.removeAll(caseDelta); + + return caseDelta; + } + private boolean containsPhotoModification(Collection modifications) { ItemPath photoPath = new ItemPath(FocusType.F_JPEG_PHOTO); for (ItemDelta delta : modifications) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 2b9b1c7f31a..2036a95e891 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -17,21 +17,29 @@ package com.evolveum.midpoint.repo.sql.data.common; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; import org.hibernate.annotations.ForeignKey; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Table; +import javax.persistence.Transient; import javax.persistence.UniqueConstraint; import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @Entity @Table(name = RAccessCertificationCampaign.TABLE_NAME, @@ -43,6 +51,7 @@ public class RAccessCertificationCampaign extends RObject cases; @Embedded public RPolyString getName() { @@ -62,6 +71,15 @@ public void setDefinitionRef(REmbeddedReference definitionRef) { this.definitionRef = definitionRef; } + @Transient + public Set getCases() { + return cases; + } + + public void setCases(Set cases) { + this.cases = cases; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -74,6 +92,9 @@ public boolean equals(Object o) { return false; if (definitionRef != null ? !definitionRef.equals(rACR.definitionRef) : rACR.definitionRef != null) return false; + + // TODO what about cases? + return true; } @@ -92,6 +113,17 @@ public static void copyFromJAXB(AccessCertificationCampaignType jaxb, RAccessCer RObject.copyFromJAXB(jaxb, repo, prismContext, generatorResult); repo.setName(RPolyString.copyFromJAXB(jaxb.getName())); repo.setDefinitionRef(RUtil.jaxbRefToEmbeddedRepoRef(jaxb.getDefinitionRef(), prismContext)); + + List cases = jaxb.getCase(); + if (!cases.isEmpty()) { + repo.setCases(new HashSet()); + for (AccessCertificationCaseType case1 : cases) { + RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(repo, case1, prismContext); + rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); + repo.getCases().add(rCase); + } + } + } @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 13a5a067ae4..75d71aaae23 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -74,6 +74,9 @@ @NamedQuery(name = "get.lookupTableLastId", query = "select max(r.id) from RLookupTableRow r where r.ownerOid = :oid"), @NamedQuery(name = "delete.lookupTableData", query = "delete RLookupTableRow r where r.ownerOid = :oid"), @NamedQuery(name = "delete.lookupTableDataRow", query = "delete RLookupTableRow r where r.ownerOid = :oid and r.id = :id"), + @NamedQuery(name = "get.campaignCaseLastId", query = "select max(c.id) from RAccessCertificationCase c where c.ownerOid = :oid"), + @NamedQuery(name = "delete.campaignCases", query = "delete RAccessCertificationCase c where c.ownerOid = :oid"), + @NamedQuery(name = "delete.campaignCase", query = "delete RAccessCertificationCase c where c.ownerOid = :oid and c.id = :id"), @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), }) @Entity diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java new file mode 100644 index 00000000000..631fe92326a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.container; + +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.parser.XNodeProcessorEvaluationMode; +import com.evolveum.midpoint.repo.sql.data.common.Metadata; +import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.any.RAssignmentExtension; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RActivation; +import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedNamedReference; +import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; +import com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner; +import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; +import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; +import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Where; + +import javax.persistence.Column; +import javax.persistence.ConstraintMode; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.ForeignKey; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.Index; +import javax.persistence.JoinColumn; +import javax.persistence.JoinColumns; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Transient; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +/** + * @author lazyman + * @author mederly + */ + +@JaxbType(type = AccessCertificationCaseType.class) +@Entity +@IdClass(RContainerId.class) +@Table(name = "m_acc_cert_case", indexes = { + @Index(name = "iObjectRefTargetOid", columnList = "objectRef_targetOid"), + @Index(name = "iTargetRefTargetOid", columnList = "targetRef_targetOid") +}) +public class RAccessCertificationCase implements Container { + + private static final Trace LOGGER = TraceManager.getTrace(RAccessCertificationCase.class); + + private Boolean trans; + + private byte[] fullObject; + + private RObject owner; + private String ownerOid; + private Integer id; + + private REmbeddedNamedReference objectRef; + private REmbeddedNamedReference targetRef; + + public RAccessCertificationCase() { + this(null); + } + + public RAccessCertificationCase(RObject owner) { + this.setOwner(owner); + } + + @Id + @org.hibernate.annotations.ForeignKey(name = "fk_ac_case_owner") + @MapsId("owner") + @ManyToOne(fetch = FetchType.LAZY) + public RObject getOwner() { + return owner; + } + + @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + public String getOwnerOid() { + if (owner != null && ownerOid == null) { + ownerOid = owner.getOid(); + } + return ownerOid; + } + + @Id + @GeneratedValue(generator = "ContainerIdGenerator") + @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") + @Column(name = "id") + public Integer getId() { + return id; + } + + @Embedded + public REmbeddedNamedReference getTargetRef() { + return targetRef; + } + + @Embedded + public REmbeddedNamedReference getObjectRef() { + return objectRef; + } + + public void setOwner(RObject owner) { + this.owner = owner; + } + + public void setOwnerOid(String ownerOid) { + this.ownerOid = ownerOid; + } + + public void setId(Integer id) { + this.id = id; + } + + public void setTargetRef(REmbeddedNamedReference targetRef) { + this.targetRef = targetRef; + } + + public void setObjectRef(REmbeddedNamedReference objectRef) { + this.objectRef = objectRef; + } + + @Lob + public byte[] getFullObject() { + return fullObject; + } + + public void setFullObject(byte[] fullObject) { + this.fullObject = fullObject; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RAccessCertificationCase that = (RAccessCertificationCase) o; + + if (targetRef != null ? !targetRef.equals(that.targetRef) : that.targetRef != null) return false; + if (objectRef != null ? !objectRef.equals(that.objectRef) : that.objectRef != null) return false; + if (fullObject != null ? !Arrays.equals(fullObject, that.fullObject) : that.fullObject != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (targetRef != null ? targetRef.hashCode() : 0); + result = 31 * result + (objectRef != null ? objectRef.hashCode() : 0); + return result; + } + + public static void copyFromJAXB(AccessCertificationCaseType jaxb, RAccessCertificationCase repo, ObjectType parent, PrismContext prismContext, + IdGeneratorResult generatorResult) throws DtoTranslationException { + Validate.notNull(repo, "Repo object must not be null."); + Validate.notNull(jaxb, "JAXB object must not be null."); + + repo.setOwnerOid(parent.getOid()); + //repo.setId(RUtil.toInteger(jaxb.getId())); + + repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getTargetRef(), prismContext)); + repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getObjectRef(), prismContext)); + } + + @Override + public String toString() { + return "RAccessCertificationCase{" + + "id=" + id + + ", ownerOid='" + ownerOid + '\'' + + ", owner=" + owner + + ", targetRef=" + targetRef + + ", objectRef=" + objectRef + + '}'; + } + + @Override + public Boolean isTransient() { + return trans; + } + + @Override + public void setTransient(Boolean trans) { + this.trans = trans; + } + + public static RAccessCertificationCase toRepo(RAccessCertificationCampaign owner, AccessCertificationCaseType case1, PrismContext prismContext) { + RAccessCertificationCase rCase = toRepo(case1, prismContext); + rCase.setOwner(owner); + return rCase; + } + + public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificationCaseType case1, PrismContext prismContext) { + RAccessCertificationCase rCase = toRepo(case1, prismContext); + rCase.setOwnerOid(ownerOid); + return rCase; + } + + private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, PrismContext prismContext) { + RAccessCertificationCase rCase = new RAccessCertificationCase(); + rCase.setId(RUtil.toInteger(case1.getId())); + rCase.setObjectRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getObjectRef(), prismContext)); + rCase.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getTargetRef(), prismContext)); + + String xml; + try { + xml = prismContext.serializeContainerValueToString(case1.asPrismContainerValue(), new QName("value"), PrismContext.LANG_XML); + } catch (SchemaException e) { + throw new IllegalStateException("Couldn't serialize certification case to string", e); + } + byte[] fullObject = RUtil.getByteArrayFromXml(xml, false); + rCase.setFullObject(fullObject); + + return rCase; + } + + public AccessCertificationCaseType toJAXB(PrismContext prismContext) throws SchemaException { + String xml = RUtil.getXmlFromByteArray(fullObject, false); + PrismContainer caseContainer; + try { + // TODO tolerant mode + caseContainer = prismContext.parseContainer(xml, AccessCertificationCaseType.class, PrismContext.LANG_XML); + } catch (SchemaException e) { + LOGGER.debug("Couldn't parse certification case because of schema exception ({}):\nData: {}", e, xml); + throw e; + } catch (RuntimeException e) { + LOGGER.debug("Couldn't parse certification case because of unexpected exception ({}):\nData: {}", e, xml); + throw e; + } + return caseContainer.getValue().asContainerable().clone(); // clone in order to make it parent-less + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java new file mode 100644 index 00000000000..ef4ac6412cc --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.embedded; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; + +/** + * @author mederly + */ +@Embeddable +public class REmbeddedNamedReference extends REmbeddedReference { + + private RPolyString targetName; + + public RPolyString getTargetName() { + return targetName; + } + + public void setTargetName(RPolyString targetName) { + this.targetName = targetName; + } + + // these three methods are repeated here because of some hibernate weirdness + + @Column(length = RUtil.COLUMN_LENGTH_QNAME) + @Override + public String getRelation() { + return super.getRelation(); + } + + @Column(length = RUtil.COLUMN_LENGTH_OID, insertable = true, updatable = true, nullable = true) + @Override + public String getTargetOid() { + return super.getTargetOid(); + } + + @Enumerated(EnumType.ORDINAL) + @Override + public RObjectType getType() { + return super.getType(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof REmbeddedNamedReference)) return false; + if (!super.equals(o)) return false; + + REmbeddedNamedReference that = (REmbeddedNamedReference) o; + + return !(targetName != null ? !targetName.equals(that.targetName) : that.targetName != null); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (targetName != null ? targetName.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); + } + + public static void copyToJAXB(REmbeddedNamedReference repo, ObjectReferenceType jaxb, PrismContext prismContext) { + Validate.notNull(repo, "Repo object must not be null."); + Validate.notNull(jaxb, "JAXB object must not be null."); + REmbeddedReference.copyToJAXB(repo, jaxb, prismContext); + + jaxb.setTargetName(RPolyString.copyToJAXB(repo.getTargetName())); + } + + public static void copyFromJAXB(ObjectReferenceType jaxb, REmbeddedNamedReference repo, PrismContext prismContext) { + Validate.notNull(repo, "Repo object must not be null."); + Validate.notNull(jaxb, "JAXB object must not be null."); + Validate.notEmpty(jaxb.getOid(), "Target oid must not be null."); + REmbeddedReference.copyFromJAXB(jaxb, repo, prismContext); + + repo.setTargetName(RPolyString.copyFromJAXB(jaxb.getTargetName())); + } + + public ObjectReferenceType toJAXB(PrismContext prismContext) { + ObjectReferenceType ref = new ObjectReferenceType(); + copyToJAXB(this, ref, prismContext); + return ref; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/RUtil.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/RUtil.java index e55268c2b1e..02cfdf2bed4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/RUtil.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/RUtil.java @@ -32,6 +32,7 @@ import com.evolveum.midpoint.repo.sql.data.common.container.RAssignmentReference; import com.evolveum.midpoint.repo.sql.data.common.container.RExclusion; import com.evolveum.midpoint.repo.sql.data.common.container.RTrigger; +import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedNamedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.enums.ROperationResultStatus; @@ -227,6 +228,16 @@ public static REmbeddedReference jaxbRefToEmbeddedRepoRef(ObjectReferenceType ja return ref; } + public static REmbeddedNamedReference jaxbRefToEmbeddedNamedRepoRef(ObjectReferenceType jaxb, PrismContext prismContext) { + if (jaxb == null) { + return null; + } + REmbeddedNamedReference ref = new REmbeddedNamedReference(); + REmbeddedNamedReference.copyFromJAXB(jaxb, ref, prismContext); + + return ref; + } + public static Integer getIntegerFromString(String val) { if (val == null || !val.matches("[0-9]+")) { return null; From 7fc6133a4480d4bf78e5ba9837f0173f596d229f Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 17 Nov 2015 14:53:12 +0100 Subject: [PATCH 005/116] Certification case stores searchable targetRef, ownerRef, reviewerRef. --- .../midpoint/prism/query/RefFilter.java | 1 + .../xml/ns/public/common/common-3.xsd | 5 +- .../midpoint/repo/api/RepositoryService.java | 25 ++- .../midpoint/repo/cache/RepositoryCache.java | 8 +- .../repo/sql/SqlRepositoryServiceImpl.java | 80 ++++++++- .../container/RAccessCertificationCase.java | 47 +++-- .../container/RAssignmentReference.java | 113 +----------- .../common/container/RCertCaseReference.java | 161 +++++++++++++++++ .../common/container/RContainerReference.java | 163 ++++++++++++++++++ .../data/common/other/RCReferenceOwner.java | 6 +- .../data/common/other/RReferenceOwner.java | 18 +- .../query/restriction/ItemRestriction.java | 1 - 12 files changed, 481 insertions(+), 147 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java index ae52b632c7f..25e60559ab3 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java @@ -214,6 +214,7 @@ private boolean isInFilterItem(PrismReferenceValue v, Item filterItem) { if (filterRV.getOid().equals(v.getOid())) { return true; } + // TODO compare relation and target type as well (see repo implementation in ReferenceRestriction) } return false; } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 3a4caca3523..66b9af61885 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -2010,7 +2010,7 @@ - + @@ -7136,7 +7136,8 @@ - + + diff --git a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java index bc143502a81..3a65548f14d 100644 --- a/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java +++ b/repo/repo-api/src/main/java/com/evolveum/midpoint/repo/api/RepositoryService.java @@ -20,6 +20,7 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.query.ObjectPaging; @@ -137,6 +138,7 @@ public interface RepositoryService { @Deprecated String RELEASE_TASK = CLASS_NAME_WITH_DOT + "releaseTask"; String SEARCH_OBJECTS = CLASS_NAME_WITH_DOT + "searchObjects"; + String SEARCH_CONTAINERS = CLASS_NAME_WITH_DOT + "searchContainers"; String LIST_RESOURCE_OBJECT_SHADOWS = CLASS_NAME_WITH_DOT + "listResourceObjectShadows"; String MODIFY_OBJECT = CLASS_NAME_WITH_DOT + "modifyObject"; String COUNT_OBJECTS = CLASS_NAME_WITH_DOT + "countObjects"; @@ -166,10 +168,15 @@ public interface RepositoryService { * @throws IllegalArgumentException * wrong OID format, etc. */ - PrismObject getObject(Class type,String oid, Collection> options, + PrismObject getObject(Class type, String oid, Collection> options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException; +// PrismObject getContainerValue(Class type, String oid, long id, +// Collection> options, +// OperationResult parentResult) +// throws ObjectNotFoundException, SchemaException; + /** * Returns object version for provided OID. * @@ -269,6 +276,22 @@ SearchResultList> searchObjects(Class Collection> options, OperationResult parentResult) throws SchemaException; + /** + * Search for "sub-object" structures, i.e. containers. + * Currently, only one type of search is available: certification case search. + * + * @param type + * @param query + * @param options + * @param parentResult + * @param + * @return + * @throws SchemaException + */ + SearchResultList searchContainers(Class type, ObjectQuery query, + Collection> options, OperationResult parentResult) + throws SchemaException; + /** *

Search for objects in the repository in an iterative fashion.

*

Searches through all object types. Calls a specified handler for each object found. diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java index fe4aa0de40a..d42c89c7810 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java @@ -15,6 +15,7 @@ */ package com.evolveum.midpoint.repo.cache; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ItemDelta; @@ -186,7 +187,12 @@ public SearchResultList> searchObjects(Cla } return objects; } - + + @Override + public SearchResultList searchContainers(Class type, ObjectQuery query, Collection> options, OperationResult parentResult) throws SchemaException { + return repository.searchContainers(type, query, options, parentResult); + } + /* (non-Javadoc) * @see com.evolveum.midpoint.repo.api.RepositoryService#searchObjectsIterative(java.lang.Class, com.evolveum.midpoint.prism.query.ObjectQuery, com.evolveum.midpoint.schema.ResultHandler, com.evolveum.midpoint.schema.result.OperationResult) */ diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 12d7673a818..6d7a5c245c2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -36,6 +36,7 @@ import javax.annotation.PostConstruct; import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; @@ -1066,7 +1067,55 @@ public SearchResultList> searchObjects(Cla } } - private void logSearchInputParameters(Class type, ObjectQuery query, boolean iterative, Boolean strictlySequential) { + @Override + public SearchResultList searchContainers(Class type, ObjectQuery query, + Collection> options, OperationResult parentResult) + throws SchemaException { + Validate.notNull(type, "Object type must not be null."); + Validate.notNull(parentResult, "Operation result must not be null."); + + logSearchInputParameters(type, query, false, null); + + OperationResult result = parentResult.createSubresult(SEARCH_CONTAINERS); + result.addParam("type", type.getName()); + result.addParam("query", query); + + if (query != null) { + ObjectFilter filter = query.getFilter(); + filter = ObjectQueryUtil.simplify(filter); + if (filter instanceof NoneFilter) { + result.recordSuccess(); + return new SearchResultList(new ArrayList(0)); + //shouldn't be this in ObjectQueryUtil.simplify? + } else if (filter instanceof AllFilter) { + query = query.cloneEmpty(); + query.setFilter(null); + } else { + query = query.cloneEmpty(); + query.setFilter(filter); + } + } + + SqlPerformanceMonitor pm = getPerformanceMonitor(); + long opHandle = pm.registerOperationStart("searchContainers"); + + final String operation = "searching"; + int attempt = 1; + try { + while (true) { + try { + return searchContainersAttempt(type, query, options, result); + } catch (RuntimeException ex) { + attempt = logOperationAttempt(null, operation, attempt, ex, result); + pm.registerOperationNewTrial(opHandle, attempt); + } + } + } finally { + pm.registerOperationFinish(opHandle, attempt); + } + } + + private void logSearchInputParameters(Class type, ObjectQuery query, boolean iterative, Boolean strictlySequential) { ObjectPaging paging = query != null ? query.getPaging() : null; LOGGER.debug("Searching objects of type '{}', query (on trace level), offset {}, count {}, iterative {}, strictlySequential {}.", new Object[]{type.getSimpleName(), (paging != null ? paging.getOffset() : "undefined"), @@ -1117,6 +1166,35 @@ private SearchResultList> searchObjectsAtt return new SearchResultList>(list); } + private SearchResultList searchContainersAttempt(Class type, ObjectQuery query, + Collection> options, + OperationResult result) throws SchemaException { + LOGGER_PERFORMANCE.debug("> search containers {}", new Object[]{type.getSimpleName()}); + List list = new ArrayList<>(); + Session session = null; + try { + session = beginReadOnlyTransaction(); + +// RQuery rQuery = engine.interpret(query, type, options, false, session); +// +// List objects = rQuery.list(); +// LOGGER.trace("Found {} objects, translating to JAXB.", new Object[]{(objects != null ? objects.size() : 0)}); +// +// for (GetObjectResult object : objects) { +// PrismObject prismObject = updateLoadedObject(object, type, options, session); +// list.add(prismObject); +// } + + session.getTransaction().commit(); + } catch (/*QueryException | */RuntimeException ex) { + handleGeneralException(ex, session, result); + } finally { + cleanupSessionAndResult(session, result); + } + + return new SearchResultList(list); + } + /** * This method provides object parsing from String and validation. */ diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 631fe92326a..088bf2724bd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -18,22 +18,12 @@ import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.parser.XNodeProcessorEvaluationMode; -import com.evolveum.midpoint.repo.sql.data.common.Metadata; import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RObject; -import com.evolveum.midpoint.repo.sql.data.common.any.RAssignmentExtension; -import com.evolveum.midpoint.repo.sql.data.common.embedded.RActivation; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedNamedReference; -import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; -import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; -import com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner; -import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; -import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; -import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; +import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; -import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -41,7 +31,6 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; import org.hibernate.annotations.Cascade; @@ -49,30 +38,20 @@ import org.hibernate.annotations.Where; import javax.persistence.Column; -import javax.persistence.ConstraintMode; import javax.persistence.Embedded; import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; import javax.persistence.FetchType; -import javax.persistence.ForeignKey; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Index; -import javax.persistence.JoinColumn; -import javax.persistence.JoinColumns; import javax.persistence.Lob; import javax.persistence.ManyToOne; import javax.persistence.MapsId; import javax.persistence.OneToMany; -import javax.persistence.OneToOne; import javax.persistence.Table; -import javax.persistence.Transient; -import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import java.util.Arrays; -import java.util.Date; import java.util.HashSet; import java.util.Set; @@ -100,6 +79,7 @@ public class RAccessCertificationCase implements Container { private String ownerOid; private Integer id; + private Set reviewerRef; private REmbeddedNamedReference objectRef; private REmbeddedNamedReference targetRef; @@ -135,6 +115,21 @@ public Integer getId() { return id; } + @Where(clause = RCertCaseReference.REFERENCE_TYPE + "= 3") + @OneToMany(mappedBy = "owner", orphanRemoval = true) + @org.hibernate.annotations.ForeignKey(name = "none") + @Cascade({org.hibernate.annotations.CascadeType.ALL}) + public Set getReviewerRef() { + if (reviewerRef == null) { + reviewerRef = new HashSet<>(); + } + return reviewerRef; + } + + public void setReviewerRef(Set reviewerRef) { + this.reviewerRef = reviewerRef; + } + @Embedded public REmbeddedNamedReference getTargetRef() { return targetRef; @@ -181,6 +176,7 @@ public boolean equals(Object o) { RAccessCertificationCase that = (RAccessCertificationCase) o; + if (reviewerRef != null ? !reviewerRef.equals(that.reviewerRef) : that.reviewerRef != null) return false; if (targetRef != null ? !targetRef.equals(that.targetRef) : that.targetRef != null) return false; if (objectRef != null ? !objectRef.equals(that.objectRef) : that.objectRef != null) return false; if (fullObject != null ? !Arrays.equals(fullObject, that.fullObject) : that.fullObject != null) return false; @@ -202,10 +198,12 @@ public static void copyFromJAXB(AccessCertificationCaseType jaxb, RAccessCertifi Validate.notNull(jaxb, "JAXB object must not be null."); repo.setOwnerOid(parent.getOid()); - //repo.setId(RUtil.toInteger(jaxb.getId())); + repo.setId(RUtil.toInteger(jaxb.getId())); repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getTargetRef(), prismContext)); repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getObjectRef(), prismContext)); + repo.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( + jaxb.getReviewerRef(), prismContext, repo, RCReferenceOwner.CASE_REVIEWER)); } @Override @@ -246,7 +244,8 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 rCase.setId(RUtil.toInteger(case1.getId())); rCase.setObjectRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getObjectRef(), prismContext)); rCase.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getTargetRef(), prismContext)); - + rCase.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( + case1.getReviewerRef(), prismContext, rCase, RCReferenceOwner.CASE_REVIEWER)); String xml; try { xml = prismContext.serializeContainerValueToString(case1.asPrismContainerValue(), new QName("value"), PrismContext.LANG_XML); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java index d8b83ee9cdf..f99728fc316 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java @@ -16,20 +16,14 @@ package com.evolveum.midpoint.repo.sql.data.common.container; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; -import com.evolveum.midpoint.repo.sql.data.common.RObjectReference; import com.evolveum.midpoint.repo.sql.data.common.id.RCObjectReferenceId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; -import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import org.apache.commons.lang.Validate; import org.hibernate.annotations.ForeignKey; -import org.hibernate.annotations.Index; import javax.persistence.*; @@ -42,25 +36,9 @@ @Table(name = "m_assignment_reference", indexes = { @javax.persistence.Index(name = "iAssignmentReferenceTargetOid", columnList = "targetOid") }) -public class RAssignmentReference implements ObjectReference { +public class RAssignmentReference extends RContainerReference { - public static final String REFERENCE_TYPE = "reference_type"; - - public static final String F_OWNER = "owner"; - - private RCReferenceOwner referenceType; - - //owner private RAssignment owner; - private String ownerOid; - private Integer ownerId; - //other primary key fields - private String targetOid; - private String relation; - private RObjectType type; - - public RAssignmentReference() { - } @ForeignKey(name = "fk_assignment_reference") @MapsId("owner") @@ -72,33 +50,27 @@ public RAssignment getOwner() { @Id @Column(name = "owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) public String getOwnerOid() { - if (ownerOid == null && owner != null) { - ownerOid = owner.getOwnerOid(); - } - return ownerOid; + return super.getOwnerOid(); } @Id @Column(name = "owner_id") public Integer getOwnerId() { - if (ownerId == null && owner != null) { - ownerId = owner.getId(); - } - return ownerId; + return super.getOwnerId(); } @Id @Column(name = "targetOid", length = RUtil.COLUMN_LENGTH_OID) @Override public String getTargetOid() { - return targetOid; + return super.getTargetOid(); } @Id @Column(name="relation", length = RUtil.COLUMN_LENGTH_QNAME) public String getRelation() { - return relation; + return super.getRelation(); } /** @@ -112,87 +84,16 @@ public String getRelation() { @Enumerated(EnumType.ORDINAL) @Override public RObjectType getType() { - return type; + return super.getType(); } @Id @Column(name = REFERENCE_TYPE, nullable = false) public RCReferenceOwner getReferenceType() { - return referenceType; + return super.getReferenceType(); } - public void setReferenceType(RCReferenceOwner referenceType) { this.referenceType = referenceType; } - public void setOwner(RAssignment owner) { this.owner = owner; } - - public void setOwnerOid(String ownerOid) { - this.ownerOid = ownerOid; - } - - public void setOwnerId(Integer ownerId) { - this.ownerId = ownerId; - } - - public void setRelation(String relation) { - this.relation = relation; - } - - public void setTargetOid(String targetOid) { - this.targetOid = targetOid; - } - - public void setType(RObjectType type) { - this.type = type; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - RAssignmentReference ref = (RAssignmentReference) o; - - if (targetOid != null ? !targetOid.equals(ref.targetOid) : ref.targetOid != null) return false; - if (type != ref.type) return false; - - return true; - } - - @Override - public int hashCode() { - int result = targetOid != null ? targetOid.hashCode() : 0; - result = 31 * result + (type != null ? type.hashCode() : 0); - result = 31 * result + (relation != null ? relation.hashCode() : 0); - - return result; - } - - public static void copyToJAXB(RAssignmentReference repo, ObjectReferenceType jaxb, PrismContext prismContext) { - Validate.notNull(repo, "Repo object must not be null."); - Validate.notNull(jaxb, "JAXB object must not be null."); - - jaxb.setType(ClassMapper.getQNameForHQLType(repo.getType())); - jaxb.setOid(repo.getTargetOid()); - jaxb.setRelation(RUtil.stringToQName(repo.getRelation())); - } - - public static void copyFromJAXB(ObjectReferenceType jaxb, RAssignmentReference repo, PrismContext prismContext) { - Validate.notNull(repo, "Repo object must not be null."); - Validate.notNull(jaxb, "JAXB object must not be null."); - Validate.notEmpty(jaxb.getOid(), "Target oid must not be null."); - - repo.setType(ClassMapper.getHQLTypeForQName(jaxb.getType())); - repo.setRelation(RUtil.qnameToString(jaxb.getRelation())); - - repo.setTargetOid(jaxb.getOid()); - } - - public ObjectReferenceType toJAXB(PrismContext prismContext) { - ObjectReferenceType ref = new ObjectReferenceType(); - copyToJAXB(this, ref, prismContext); - - return ref; - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java new file mode 100644 index 00000000000..27508e8a6d9 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.container; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.data.common.id.RCObjectReferenceId; +import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import org.apache.commons.lang.Validate; +import org.hibernate.annotations.ForeignKey; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; +import javax.persistence.Table; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author lazyman + * @author mederly + * + * Reference contained in a certification case. + * + */ +@JaxbType(type = ObjectReferenceType.class) +@Entity +@IdClass(RCObjectReferenceId.class) +@Table(name = "m_acc_cert_case_reference", indexes = { + @javax.persistence.Index(name = "iAccCertCaseReferenceTargetOid", columnList = "targetOid") +}) +public class RCertCaseReference extends RContainerReference { + + private RAccessCertificationCase owner; + +// private RPolyString targetName; +// +// public RPolyString getTargetName() { +// return targetName; +// } + + @ForeignKey(name = "fk_acc_cert_case_reference") + @MapsId("owner") + @ManyToOne(fetch = FetchType.LAZY) + public RAccessCertificationCase getOwner() { + return owner; + } + + @Id + @Column(name = "owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + public String getOwnerOid() { + return super.getOwnerOid(); + } + + + @Id + @Column(name = "owner_id") + public Integer getOwnerId() { + return super.getOwnerId(); + } + + @Id + @Column(name = "targetOid", length = RUtil.COLUMN_LENGTH_OID) + @Override + public String getTargetOid() { + return super.getTargetOid(); + } + + @Id + @Column(name="relation", length = RUtil.COLUMN_LENGTH_QNAME) + public String getRelation() { + return super.getRelation(); + } + + /** + * Represents {@link javax.xml.namespace.QName} type attribute in reference e.g. + * {@link com.evolveum.midpoint.xml.ns._public.common.common_3.UserType} represented + * as enum {@link RObjectType#USER} + * + * @return null if not defined, otherwise value from {@link RObjectType} enum + */ + @Column(name = "containerType") + @Enumerated(EnumType.ORDINAL) + @Override + public RObjectType getType() { + return super.getType(); + } + + @Id + @Column(name = REFERENCE_TYPE, nullable = false) + public RCReferenceOwner getReferenceType() { + return super.getReferenceType(); + } + + public void setOwner(RAccessCertificationCase owner) { + this.owner = owner; + } + +// public void setTargetName(RPolyString targetName) { +// this.targetName = targetName; +// } + + public static Set safeListReferenceToSet(List list, PrismContext prismContext, + RAccessCertificationCase owner, RCReferenceOwner refOwner) { + Set set = new HashSet<>(); + if (list == null || list.isEmpty()) { + return set; + } + + for (ObjectReferenceType ref : list) { + RCertCaseReference rRef = jaxbRefToRepo(ref, prismContext, owner, refOwner); + if (rRef != null) { + set.add(rRef); + } + } + return set; + } + + public static RCertCaseReference jaxbRefToRepo(ObjectReferenceType reference, PrismContext prismContext, + RAccessCertificationCase owner, RCReferenceOwner refOwner) { + if (reference == null) { + return null; + } + Validate.notNull(owner, "Owner of reference must not be null."); + Validate.notNull(refOwner, "Reference owner of reference must not be null."); + Validate.notEmpty(reference.getOid(), "Target oid reference must not be null."); + + RCertCaseReference repoRef = new RCertCaseReference(); + repoRef.setReferenceType(refOwner); + repoRef.setOwner(owner); + RCertCaseReference.copyFromJAXB(reference, repoRef, prismContext); +// repoRef.setTargetName(RPolyString.toRepo(reference.asReferenceValue().getTargetName())); + + return repoRef; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java new file mode 100644 index 00000000000..1e474fa4e71 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.container; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import org.apache.commons.lang.Validate; + +/** + * @author lazyman + * @author mederly + * + * This is a reference that is contained in (any) container. Its owner is identified by OID, container value ID, + * and owner type. + * + * It is created as a superclass for both RAssignmentReference and RCertCaseReference because they share + * almost all the code. + * + */ +public abstract class RContainerReference implements ObjectReference { + + public static final String REFERENCE_TYPE = "reference_type"; + + public static final String F_OWNER = "owner"; + + private RCReferenceOwner referenceType; + + //owner + private String ownerOid; + private Integer ownerId; + //other primary key fields + private String targetOid; + private String relation; + private RObjectType type; + + public RContainerReference() { + } + + protected abstract Container getOwner(); + + protected String getOwnerOid() { + if (ownerOid == null && getOwner() != null) { + ownerOid = getOwner().getOwnerOid(); + } + return ownerOid; + } + + protected Integer getOwnerId() { + if (ownerId == null && getOwner() != null) { + ownerId = getOwner().getId(); + } + return ownerId; + } + + @Override + public String getTargetOid() { + return targetOid; + } + + @Override + public String getRelation() { + return relation; + } + + @Override + public RObjectType getType() { + return type; + } + + protected RCReferenceOwner getReferenceType() { + return referenceType; + } + + public void setReferenceType(RCReferenceOwner referenceType) { this.referenceType = referenceType; } + + public void setOwnerOid(String ownerOid) { + this.ownerOid = ownerOid; + } + + public void setOwnerId(Integer ownerId) { + this.ownerId = ownerId; + } + + public void setRelation(String relation) { + this.relation = relation; + } + + public void setTargetOid(String targetOid) { + this.targetOid = targetOid; + } + + public void setType(RObjectType type) { + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RContainerReference ref = (RContainerReference) o; + + if (targetOid != null ? !targetOid.equals(ref.targetOid) : ref.targetOid != null) return false; + if (type != ref.type) return false; + + return true; + } + + @Override + public int hashCode() { + int result = targetOid != null ? targetOid.hashCode() : 0; + result = 31 * result + (type != null ? type.hashCode() : 0); + result = 31 * result + (relation != null ? relation.hashCode() : 0); + + return result; + } + + public static void copyToJAXB(RContainerReference repo, ObjectReferenceType jaxb, PrismContext prismContext) { + Validate.notNull(repo, "Repo object must not be null."); + Validate.notNull(jaxb, "JAXB object must not be null."); + + jaxb.setType(ClassMapper.getQNameForHQLType(repo.getType())); + jaxb.setOid(repo.getTargetOid()); + jaxb.setRelation(RUtil.stringToQName(repo.getRelation())); + } + + public static void copyFromJAXB(ObjectReferenceType jaxb, RContainerReference repo, PrismContext prismContext) { + Validate.notNull(repo, "Repo object must not be null."); + Validate.notNull(jaxb, "JAXB object must not be null."); + Validate.notEmpty(jaxb.getOid(), "Target oid must not be null."); + + repo.setType(ClassMapper.getHQLTypeForQName(jaxb.getType())); + repo.setRelation(RUtil.qnameToString(jaxb.getRelation())); + + repo.setTargetOid(jaxb.getOid()); + } + + public ObjectReferenceType toJAXB(PrismContext prismContext) { + ObjectReferenceType ref = new ObjectReferenceType(); + copyToJAXB(this, ref, prismContext); + + return ref; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RCReferenceOwner.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RCReferenceOwner.java index 7e729445a71..887a0b63480 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RCReferenceOwner.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RCReferenceOwner.java @@ -24,7 +24,9 @@ */ public enum RCReferenceOwner { - CREATE_APPROVER, + CREATE_APPROVER, // 0 - MODIFY_APPROVER; + MODIFY_APPROVER, // 1 + + CASE_REVIEWER; // 2 } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RReferenceOwner.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RReferenceOwner.java index 5031a8bccb3..06dae69be8f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RReferenceOwner.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RReferenceOwner.java @@ -24,25 +24,25 @@ */ public enum RReferenceOwner { - OBJECT_PARENT_ORG, + OBJECT_PARENT_ORG, // 0 - USER_ACCOUNT, + USER_ACCOUNT, // 1 - RESOURCE_BUSINESS_CONFIGURATON_APPROVER, + RESOURCE_BUSINESS_CONFIGURATON_APPROVER, // 2 - ROLE_APPROVER, + ROLE_APPROVER, // 3 /** * @deprecated */ @Deprecated - SYSTEM_CONFIGURATION_ORG_ROOT, + SYSTEM_CONFIGURATION_ORG_ROOT, // 4 - CREATE_APPROVER, + CREATE_APPROVER, // 5 - MODIFY_APPROVER, + MODIFY_APPROVER, // 6 - INCLUDE, + INCLUDE, // 7 - ROLE_MEMBER; + ROLE_MEMBER; // 8 } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/restriction/ItemRestriction.java index c421247ea93..0f30049cd5e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/restriction/ItemRestriction.java @@ -69,7 +69,6 @@ public boolean canHandle(ObjectFilter filter) throws QueryException { @Override public Criterion interpret() throws QueryException { -// ItemPath path = RUtil.createFullPath(filter); ItemPath path = filter.getFullPath(); if (path != null) { // at first we build criterias with aliases From 9967a7cf73e3ddc240a730f08301f3c6fce9f556 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 17 Nov 2015 14:53:36 +0100 Subject: [PATCH 006/116] Diagnosing suspicious error message in repo cache. --- .../src/main/java/com/evolveum/midpoint/repo/cache/Cache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/Cache.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/Cache.java index f1bea704206..258677f7eca 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/Cache.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/Cache.java @@ -101,7 +101,7 @@ private QueryKey createQueryKey(Class type, ObjectQuery qu try { return new QueryKey(type, query, prismContext); } catch (Exception e) { // TODO THIS IS REALLY UGLY HACK - query converter / prism serializer refuse to serialize some queries - should be fixed RSN! - LoggingUtils.logException(LOGGER, "Couldn't create query key. Although this particular exception is harmless, please fix prism implementation!", e); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create query key. Although this particular exception is harmless, please fix prism implementation!", e); return null; // we "treat" it so that we simply pretend the entry is not in the cache and/or refuse to enter it into the cache } } From dba62a79424f485a2db9124d593680bd69798b72 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 17 Nov 2015 15:40:17 +0100 Subject: [PATCH 007/116] Paging.orderBy changed from QName to ItemPath. --- .../midpoint/prism/query/ObjectPaging.java | 21 +++++++++++++------ .../midpoint/prism/query/PagingConvertor.java | 2 +- .../impl/AccCertQueryHelper.java | 12 +++++------ .../ucf/impl/ConnectorInstanceIcfImpl.java | 9 ++++++-- .../repo/sql/SqlRepositoryServiceImpl.java | 11 +++++++--- .../repo/sql/query/QueryInterpreter.java | 5 +++-- .../custom/ShadowQueryWithDisjunction.java | 4 ++-- 7 files changed, 42 insertions(+), 22 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java index e8d0d93205c..f52e6480e89 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java @@ -20,6 +20,7 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; @@ -27,7 +28,7 @@ public class ObjectPaging implements DebugDumpable, Serializable { private Integer offset; private Integer maxSize; - private QName orderBy; + private ItemPath orderBy; private OrderDirection direction; private String cookie; @@ -39,8 +40,8 @@ protected ObjectPaging() { this.offset = offset; this.maxSize = maxSize; } - - ObjectPaging(Integer offset, Integer maxSize, QName orderBy, OrderDirection direction){ + + ObjectPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction){ this.offset = offset; this.maxSize = maxSize; this.orderBy = orderBy; @@ -52,11 +53,15 @@ public static ObjectPaging createPaging(Integer offset, Integer maxSize){ } public static ObjectPaging createPaging(Integer offset, Integer maxSize, QName orderBy, OrderDirection direction){ + return new ObjectPaging(offset, maxSize, new ItemPath(orderBy), direction); + } + + public static ObjectPaging createPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction){ return new ObjectPaging(offset, maxSize, orderBy, direction); } public static ObjectPaging createPaging(Integer offset, Integer maxSize, String orderBy, String namespace, OrderDirection direction){ - return new ObjectPaging(offset, maxSize, new QName(namespace, orderBy), direction); + return createPaging(offset, maxSize, new QName(namespace, orderBy), direction); } public static ObjectPaging createEmptyPaging(){ @@ -78,11 +83,15 @@ public void setOffset(Integer offset) { this.offset = offset; } - public QName getOrderBy() { + public ItemPath getOrderBy() { return orderBy; } public void setOrderBy(QName orderBy) { + this.orderBy = new ItemPath(orderBy); + } + + public void setOrderBy(ItemPath orderBy) { this.orderBy = orderBy; } @@ -195,7 +204,7 @@ public String toString() { } if (getOrderBy() != null){ sb.append("BY: "); - sb.append(getOrderBy().getLocalPart()); + sb.append(getOrderBy()); sb.append(", "); } if (getDirection() != null){ diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PagingConvertor.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PagingConvertor.java index 383998c8f33..a1e2d201851 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PagingConvertor.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PagingConvertor.java @@ -71,7 +71,7 @@ public static PagingType createPagingType(ObjectPaging paging){ pagingType.setMaxSize(paging.getMaxSize()); pagingType.setOffset(paging.getOffset()); if (paging.getOrderBy() != null) { - pagingType.setOrderBy(new ItemPathType(new ItemPath(paging.getOrderBy()))); + pagingType.setOrderBy(new ItemPathType(paging.getOrderBy())); } return pagingType; diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java index 4416e48fc28..5aab0fd1ad4 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java @@ -222,16 +222,16 @@ protected List getCases(AccessCertificationCampaign * The requirement is that object names were fetched as well (resolveNames option) * */ - private Comparator createComparator(QName orderBy, OrderDirection direction) { - if (QNameUtil.match(orderBy, AccessCertificationCaseType.F_OBJECT_REF)) { + private Comparator createComparator(ItemPath orderBy, OrderDirection direction) { + if (new ItemPath(AccessCertificationCaseType.F_OBJECT_REF).equivalent(orderBy)) { return createObjectNameComparator(direction); - } else if (QNameUtil.match(orderBy, AccessCertificationCaseType.F_TARGET_REF)) { + } else if (new ItemPath(AccessCertificationCaseType.F_TARGET_REF).equivalent(orderBy)) { return createTargetNameComparator(direction); - } else if (QNameUtil.match(orderBy, AccessCertificationCaseType.F_CAMPAIGN_REF)) { + } else if (new ItemPath(AccessCertificationCaseType.F_CAMPAIGN_REF).equivalent(orderBy)) { return createCampaignNameComparator(direction); - } else if (QNameUtil.match(orderBy, AccessCertificationCaseType.F_REVIEW_REQUESTED_TIMESTAMP)) { + } else if (new ItemPath(AccessCertificationCaseType.F_REVIEW_REQUESTED_TIMESTAMP).equivalent(orderBy)) { return createReviewRequestedComparator(direction); - } else if (QNameUtil.match(orderBy, AccessCertificationCaseType.F_REVIEW_DEADLINE)) { + } else if (new ItemPath(AccessCertificationCaseType.F_REVIEW_DEADLINE).equivalent(orderBy)) { return createReviewDeadlineComparator(direction); } else { LOGGER.warn("Unsupported sorting attribute {}. Results will not be sorted.", orderBy); diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/ConnectorInstanceIcfImpl.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/ConnectorInstanceIcfImpl.java index 78eab962980..99a2487d544 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/ConnectorInstanceIcfImpl.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/ConnectorInstanceIcfImpl.java @@ -31,6 +31,7 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.common.monitor.InternalMonitor; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.provisioning.impl.StateReporter; @@ -2264,8 +2265,12 @@ private void recordResume() { } QName orderBy; boolean isAscending; - if (paging.getOrderBy() != null) { - orderBy = paging.getOrderBy(); + ItemPath orderByPath = paging.getOrderBy(); + if (orderByPath != null && !orderByPath.isEmpty()) { + if (orderByPath.size() > 1 || !(orderByPath.first() instanceof NameItemPathSegment)) { + throw new SchemaException("OrderBy has to consist of just one naming segment"); + } + orderBy = ((NameItemPathSegment) (orderByPath.first())).getName(); if (SchemaConstants.C_NAME.equals(orderBy)) { orderBy = SchemaConstants.ICFS_NAME; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 6d7a5c245c2..cf8033fe845 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -40,6 +40,7 @@ import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; @@ -1335,7 +1336,7 @@ private GetOperationOptions findLookupTableGetOption(Collection void updateLoadedLookupTable(PrismObject object, Collection> options, - Session session) { + Session session) throws SchemaException { if (!SelectorOptions.hasToLoadPath(LookupTableType.F_ROW, options)) { return; } @@ -1355,8 +1356,12 @@ private void updateLoadedLookupTable(PrismObject objec criteria.setMaxResults(paging.getMaxSize()); } - if (paging.getDirection() != null && paging.getOrderBy() != null) { - String orderBy = paging.getOrderBy().getLocalPart(); + ItemPath orderByPath = paging.getOrderBy(); + if (paging.getDirection() != null && orderByPath != null && !orderByPath.isEmpty()) { + if (orderByPath.size() > 1 || !(orderByPath.first() instanceof NameItemPathSegment)) { + throw new SchemaException("OrderBy has to consist of just one naming segment"); + } + String orderBy = ((NameItemPathSegment) (orderByPath.first())).getName().getLocalPart(); switch (paging.getDirection()) { case ASCENDING: criteria.addOrder(Order.asc(orderBy)); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java index 6dd1022184a..aff1ae533c0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.query; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; @@ -205,12 +206,12 @@ public Criteria updatePagingAndSorting(Criteria query, Cl query = query.setMaxResults(paging.getMaxSize()); } - if (paging.getDirection() == null && paging.getOrderBy() == null) { + if (paging.getDirection() == null && (paging.getOrderBy() == null || paging.getOrderBy().isEmpty())) { return query; } QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance(); - if (paging.getOrderBy() == null) { + if (paging.getOrderBy() == null || paging.getOrderBy().isEmpty() || paging.getOrderBy().size() > 1 || !(paging.getOrderBy().first() instanceof NameItemPathSegment)) { LOGGER.warn("Ordering by property path with size not equal 1 is not supported '" + paging.getOrderBy() + "'."); return query; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/custom/ShadowQueryWithDisjunction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/custom/ShadowQueryWithDisjunction.java index 31bff86df6b..999c88668ac 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/custom/ShadowQueryWithDisjunction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/custom/ShadowQueryWithDisjunction.java @@ -224,14 +224,14 @@ public Criteria updatePagingAndSorting(Criteria query, Cl query = query.setMaxResults(paging.getMaxSize()); } - if (paging.getDirection() == null && paging.getOrderBy() == null) { + if (paging.getDirection() == null && (paging.getOrderBy() == null || paging.getOrderBy().isEmpty())) { return query; } QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance(); // PropertyPath path = new // XPathHolder(paging.getOrderBy()).toPropertyPath(); - if (paging.getOrderBy() == null) { + if (paging.getOrderBy() == null || paging.getOrderBy().isEmpty() || paging.getOrderBy().size() > 1 || !(paging.getOrderBy().first() instanceof NameItemPathSegment)) { LOGGER.warn("Ordering by property path with size not equal 1 is not supported '" + paging.getOrderBy() + "'."); return query; From d0e8f9cae0408f13da07d869819b90bafbaa05c4 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 19 Nov 2015 09:33:43 +0100 Subject: [PATCH 008/116] Some less important fixes/enhancements --- .../midpoint/prism/path/ItemPath.java | 6 +- .../repo/sql/QueryInterpreterTest.java | 100 +++++++++++++++++- .../common/RAccessCertificationCampaign.java | 7 +- .../container/RAccessCertificationCase.java | 4 +- 4 files changed, 113 insertions(+), 4 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index b3e49022575..cfe603ac817 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -323,7 +323,11 @@ public ItemPath namedSegmentsOnly() { return rv; } - public enum CompareResult { + public static boolean isNullOrEmpty(ItemPath itemPath) { + return itemPath == null || itemPath.isEmpty(); + } + + public enum CompareResult { EQUIVALENT, SUPERPATH, SUBPATH, diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreterTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreterTest.java index 2aab946f8ac..582bbb2b47a 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreterTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreterTest.java @@ -109,6 +109,10 @@ public void queryOrganizationNorm() throws Exception { Session session = open(); try { + /* + * ### user: Equal (organization, "asdf", PolyStringNorm) + * ==> from RUser u left join u.organization o where o.norm = 'asdf' + */ ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -118,7 +122,6 @@ public void queryOrganizationNorm() throws Exception { addFullObjectProjectionList("u", projections, false); main.setProjection(projections); - Criteria o = main.createCriteria("organization", "o", JoinType.LEFT_OUTER_JOIN); o.add(Restrictions.eq("o.norm", "asdf")); @@ -137,6 +140,10 @@ public void queryOrganizationNorm() throws Exception { public void queryOrganizationOrig() throws Exception { Session session = open(); try { + /* + * ### user: Equal (organization, "asdf", PolyStringOrig) + * ==> from RUser u left join u.organization o where o.orig = 'asdf' + */ ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -164,6 +171,11 @@ public void queryOrganizationOrig() throws Exception { public void queryOrganizationStrict() throws Exception { Session session = open(); try { + /* + * ### user: Equal (organization, "asdf") + * ==> from RUser u left join u.organization o where o.orig = 'asdf' and o.norm = 'asdf' + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, null, new PolyString("asdf", "asdf")); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -194,6 +206,10 @@ public void queryDependent() throws Exception { Session session = open(); try { + /* + * ### task: Equal (dependent, "123456") + * ==> from RTask t left join t.dependent d where d = '123456' (why "d.elements" ????) + */ Criteria main = session.createCriteria(RTask.class, "t"); Criteria d = main.createCriteria("dependent", "d", JoinType.LEFT_OUTER_JOIN); d.add(Restrictions.eq("d.elements", "123456")); @@ -234,6 +250,10 @@ public void queryClob() throws Exception { public void queryEnum() throws Exception { Session session = open(); try { + /* + * ### task: Equal (executionStatus, WAITING) + * ==> from RTask t where t.executionStatus = com.evolveum.midpoint.repo.sql.data.common.enums.RTaskExecutionStatus.WAITING + */ Criteria main = session.createCriteria(RTask.class, "t"); main.add(Restrictions.eq("executionStatus", RTaskExecutionStatus.WAITING)); ProjectionList projections = Projections.projectionList(); @@ -258,6 +278,11 @@ public void queryEnum() throws Exception { public void queryEnabled() throws Exception { Session session = open(); try { + /* + * ### task: Equal (activation/administrativeStatus, ENABLED) + * ==> from RUser u where u.activation.administrativeStatus = com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus.ENABLED + */ + Criteria main = session.createCriteria(RUser.class, "u"); main.add(Restrictions.eq("activation.administrativeStatus", RActivationStatus.ENABLED)); ProjectionList projections = Projections.projectionList(); @@ -279,6 +304,15 @@ public void queryEnabled() throws Exception { public void queryGenericLong() throws Exception { Session session = open(); try { + /* + * ### generic: And (Equal (name, "generic object", PolyStringNorm), + * Equal (c:extension/p:intType, 123)) + * ==> from RGenericObject g left join g.longs l where + * g.name.norm = 'generic object' and + * l.ownerType = com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType.EXTENSION and + * l.name = 'http://example.com/p#intType' and + * l.value = 123 + */ Criteria main = session.createCriteria(RGenericObject.class, "g"); Criteria stringExt = main.createCriteria("longs", "l", JoinType.LEFT_OUTER_JOIN); @@ -314,6 +348,22 @@ public void queryGenericLong() throws Exception { public void queryOrComposite() throws Exception { Session session = open(); try { + /* + * ### shadow: + * Or ( + * Equal (intent, "some account type"), + * Equal (attributes/f:foo, "foo value"), + * Equal (extension/p:stringType, "uid=test,dc=example,dc=com"), + * Ref (resourceRef, d0db5be9-cb93-401f-b6c1-86ffffe4cd5e)) + * + * ==> from RShadow r left join r.strings s1 where + * r.intent = 'some account type' or + * (s1.ownerType = RObjectExtensionType.ATTRIBUTES and s1.name = 'http://midpoint.evolveum.com/blabla#foo' and s1.value = 'foo value') or + * (s1.ownerType = RObjectExtensionType.EXTENSION and s1.name = 'http://example.com/p#stringType' and s1.value = 'uid=test,dc=example,dc=com') or + * (r.resourceRef.targetOid = 'd0db5be9-cb93-401f-b6c1-86ffffe4cd5e' and r.resourceRef.relation = '#' and r.resourceRef.type = '...#ResourceType') + * + * [If we used AND instead of OR, this SHOULD BE left join r.strings s1, left join r.strings s2] + */ Criteria main = session.createCriteria(RShadow.class, "r"); ProjectionList projections = Projections.projectionList(); addFullObjectProjectionList("r", projections, false); @@ -362,6 +412,13 @@ public void queryObjectByName() throws Exception { Session session = open(); try { + /* + * ### object: Equal (name, "cpt. Jack Sparrow") + * Order by name, ASC + * + * ==> from RObject o where name.orig = 'cpt. Jack Sparrow' and name.norm = 'cpt jack sparrow' + * order by name.orig asc + */ Criteria main = session.createCriteria(RObject.class, "o"); main.add(Restrictions.and( Restrictions.eq("name.orig", "cpt. Jack Sparrow"), @@ -523,6 +580,12 @@ public void queryAccountByAttributesAndResourceRef() throws Exception { public void queryUserAccountRef() throws Exception { Session session = open(); try { + /* + * ### user: Ref (linkRef, 123) + * + * ==> select from RUser u left join u.linkRef l where + * l.targetOid = '123' and l.relation = '#' + */ Criteria main = session.createCriteria(RUser.class, "u"); ProjectionList projections = Projections.projectionList(); addFullObjectProjectionList("u", projections, false); @@ -550,6 +613,15 @@ public void queryUserAccountRef() throws Exception { public void queryUserAssignmentTargetRef() throws Exception { Session session = open(); try { + /* + * ### user: Ref (assignment/targetRef, '123', RoleType) + * + * ==> select from RUser u left join u.assignments a where + * a.assignmentOwner = RAssignmentOwner.FOCUS and + * a.targetRef.targetOid = '123' and + * a.targetRef.relation = '#' and + * a.targetRef.type = RObjectType.ROLE + */ Criteria main = session.createCriteria(RUser.class, "u"); ProjectionList projections = Projections.projectionList(); addFullObjectProjectionList("u", projections, false); @@ -653,6 +725,13 @@ public void queryAssignmentActivationAdministrativeStatus() throws Exception { public void queryInducementActivationAdministrativeStatus() throws Exception { Session session = open(); try { + /* + * ### role: Equal (inducement/activation/administrativeStatus, ENABLED) + * + * ==> select from RRole r left join r.assignments a where + * a.assignmentOwner = RAssignmentOwner.ABSTRACT_ROLE and <--- this differentiates inducements from assignments + * a.activation.administrativeStatus = RActivationStatus.ENABLED + */ Criteria main = session.createCriteria(RRole.class, "r"); Criteria a = main.createCriteria("assignments", "a", JoinType.LEFT_OUTER_JOIN); a.add(Restrictions.and( @@ -686,6 +765,18 @@ public void queryInducementActivationAdministrativeStatus() throws Exception { public void queryInducementAndAssignmentActivationAdministrativeStatus() throws Exception { Session session = open(); try { + /* + * ### Role: Or (Equal (assignment/activation/administrativeStatus, RActivationStatus.ENABLED), + * Equal (inducement/activation/administrativeStatus, RActivationStatus.ENABLED)) + * + * ==> select r from RRole r left join r.assignments a where + * (a.assignmentOwner = com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner.FOCUS and + * a.activation.administrativeStatus = com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus.ENABLED) or + * (a.assignmentOwner = com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner.ABSTRACT_ROLE and + * a.activation.administrativeStatus = com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus.ENABLED) + * + * (may return duplicate results) + */ Criteria main = session.createCriteria(RRole.class, "r"); Criteria a = main.createCriteria("assignments", "a", JoinType.LEFT_OUTER_JOIN); ProjectionList projections = Projections.projectionList(); @@ -735,6 +826,13 @@ public void queryUserByActivationDouble() throws Exception { Session session = open(); try { + /* + * ### user: And (Equal (activation/administrativeStatus, RActivationStatus.ENABLED), + * Equal (activation/validFrom, '...')) + * + * ==> select u from RUser u where u.activation.administrativeStatus = RActivationStatus.ENABLED and + * u.activation.validFrom = ... + */ Criteria main = session.createCriteria(RUser.class, "u"); ProjectionList projections = Projections.projectionList(); addFullObjectProjectionList("u", projections, false); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 2036a95e891..281789bde08 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; +import com.evolveum.midpoint.repo.sql.data.common.container.RAssignment; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; @@ -29,10 +30,12 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; +import org.hibernate.annotations.Cascade; import org.hibernate.annotations.ForeignKey; import javax.persistence.Embedded; import javax.persistence.Entity; +import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Transient; import javax.persistence.UniqueConstraint; @@ -71,7 +74,9 @@ public void setDefinitionRef(REmbeddedReference definitionRef) { this.definitionRef = definitionRef; } - @Transient + @OneToMany(mappedBy = RAccessCertificationCase.F_OWNER, orphanRemoval = true) + @ForeignKey(name = "none") + @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getCases() { return cases; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 088bf2724bd..e17f4d1abf8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -71,6 +71,8 @@ public class RAccessCertificationCase implements Container { private static final Trace LOGGER = TraceManager.getTrace(RAccessCertificationCase.class); + public static final String F_OWNER = "owner"; + private Boolean trans; private byte[] fullObject; @@ -115,7 +117,7 @@ public Integer getId() { return id; } - @Where(clause = RCertCaseReference.REFERENCE_TYPE + "= 3") + @Where(clause = RCertCaseReference.REFERENCE_TYPE + "= 2") @OneToMany(mappedBy = "owner", orphanRemoval = true) @org.hibernate.annotations.ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) From 99dc92dc6c6f843f6df95c77c0a84faf71c11eb2 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 19 Nov 2015 10:01:45 +0100 Subject: [PATCH 009/116] Copied query interpreter to the experimental version (query2). --- .../repo/sql/query2/QueryContext2.java | 166 +++++ .../sql/query2/QueryDefinitionRegistry2.java | 109 +++ .../repo/sql/query2/QueryEngine2.java | 61 ++ .../repo/sql/query2/QueryInterpreter2.java | 299 +++++++++ .../repo/sql/query2/RQueryCriteriaImpl.java | 58 ++ .../midpoint/repo/sql/query2/RQueryImpl.java | 57 ++ .../repo/sql/query2/definition/Any.java | 36 + .../sql/query2/definition/AnyDefinition.java | 34 + .../definition/ClassDefinitionParser.java | 266 ++++++++ .../definition/CollectionDefinition.java | 74 +++ .../sql/query2/definition/Definition.java | 121 ++++ .../definition/DefinitionComparator.java | 55 ++ .../query2/definition/EntityDefinition.java | 177 +++++ .../repo/sql/query2/definition/JaxbName.java | 39 ++ .../repo/sql/query2/definition/JaxbType.java | 35 + .../query2/definition/PropertyDefinition.java | 77 +++ .../sql/query2/definition/QueryEntity.java | 42 ++ .../definition/ReferenceDefinition.java | 49 ++ .../query2/definition/VirtualCollection.java | 42 ++ .../VirtualCollectionDefinition.java | 51 ++ .../sql/query2/definition/VirtualEntity.java | 41 ++ .../definition/VirtualEntityDefinition.java | 51 ++ .../query2/definition/VirtualProperty.java | 41 ++ .../definition/VirtualPropertyDefinition.java | 51 ++ .../query2/definition/VirtualQueryParam.java | 37 ++ .../query2/definition/VirtualReference.java | 41 ++ .../sql/query2/matcher/DefaultMatcher.java | 34 + .../repo/sql/query2/matcher/Matcher.java | 93 +++ .../sql/query2/matcher/PolyStringMatcher.java | 82 +++ .../sql/query2/matcher/StringMatcher.java | 40 ++ .../query2/restriction/AndRestriction.java | 53 ++ .../restriction/AnyPropertyRestriction.java | 133 ++++ .../restriction/CollectionRestriction.java | 74 +++ .../query2/restriction/InOidRestriction.java | 50 ++ .../query2/restriction/ItemRestriction.java | 621 ++++++++++++++++++ .../restriction/ItemRestrictionOperation.java | 25 + .../restriction/LogicalRestriction.java | 45 ++ .../restriction/NaryLogicalRestriction.java | 80 +++ .../query2/restriction/NotRestriction.java | 52 ++ .../sql/query2/restriction/OrRestriction.java | 56 ++ .../query2/restriction/OrgRestriction.java | 106 +++ .../restriction/PropertyRestriction.java | 83 +++ .../restriction/ReferenceRestriction.java | 154 +++++ .../sql/query2/restriction/Restriction.java | 96 +++ .../query2/restriction/TypeRestriction.java | 98 +++ .../restriction/UnaryLogicalRestriction.java | 48 ++ 46 files changed, 4133 insertions(+) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryImpl.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java new file mode 100644 index 00000000000..dc0899d2ab5 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Criteria; +import org.hibernate.Session; + +import javax.xml.namespace.QName; +import java.util.HashMap; +import java.util.Map; + +/** + * @author lazyman + */ +public class QueryContext2 { + + private QueryInterpreter2 interpreter; + private PrismContext prismContext; + private Session session; + + private ObjectQuery query; + + private Class type; + + private final Map criterias = new HashMap(); + private final Map aliases = new HashMap(); + + public QueryContext2(QueryInterpreter2 interpreter, Class type, ObjectQuery query, + PrismContext prismContext, Session session) { + this.interpreter = interpreter; + this.type = type; + this.query = query; + this.prismContext = prismContext; + this.session = session; + + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + + String alias = addAlias(null, registry.findDefinition(type, null, EntityDefinition.class)); + addCriteria(null, session.createCriteria(ClassMapper.getHQLTypeClass(type), alias)); + } + + public ObjectQuery getQuery() { + return query; + } + + public void setQuery(ObjectQuery query) { + this.query = query; + } + + public PrismContext getPrismContext() { + return prismContext; + } + + public Session getSession() { + return session; + } + + public QueryInterpreter2 getInterpreter() { + return interpreter; + } + + public Class getType() { + return type; + } + + public Criteria getCriteria(ItemPath path) { + return criterias.get(path); + } + + public void addCriteria(ItemPath path, Criteria criteria) { + criterias.put(path, criteria); + } + + public String getAlias(ItemPath path) { + return aliases.get(path); + } + + public void addAlias(ItemPath path, String alias) { + if (aliases.containsKey(path)) { + if (!StringUtils.equals(alias, aliases.get(path))) { + throw new IllegalArgumentException("Path '" + path + "' (" + alias + + ") is already defined in alias map with alias (" + aliases.get(path) + ")."); + } + + return; + } + + aliases.put(path, alias); + } + + public String addAlias(ItemPath path, Definition def) { + QName qname; + if (path == null) { + //get qname from class type + qname = ObjectTypes.getObjectType(type).getQName(); + } else { + if (!path.isEmpty()) { + //get last qname from path + qname = ItemPath.getName(path.last()); + } else { + throw new IllegalArgumentException("Item path must not be empty."); + } + } + + String alias = createAlias(def, qname); + aliases.put(path, alias); + + return alias; + } + + private String createAlias(Definition def, QName qname) { + String prefix; + if (def != null) { + //we want to skip 'R' prefix for entity definition names + int prefixIndex = (def instanceof EntityDefinition) ? 1 : 0; + prefix = Character.toString(def.getJpaName().charAt(prefixIndex)).toLowerCase(); + } else { + prefix = Character.toString(qname.getLocalPart().charAt(0)).toLowerCase(); + } + + int index = 1; + String alias = prefix; + while (hasAlias(alias)) { + alias = prefix + Integer.toString(index); + index++; + + if (index > 5) { + throw new IllegalStateException("Alias index for definition '" + def + + "' is more than 5? This probably should not happen."); + } + } + + return alias; + } + + private boolean hasAlias(String alias) { + return aliases.containsValue(alias); + } + + public boolean hasAlias(ItemPath path) { + return aliases.get(path) != null; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java new file mode 100644 index 00000000000..87b9d440739 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.query2.definition.ClassDefinitionParser; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author lazyman + */ +public class QueryDefinitionRegistry2 implements DebugDumpable { + + private static final Trace LOGGER = TraceManager.getTrace(QueryDefinitionRegistry2.class); + private static final Map definitions; + + private static QueryDefinitionRegistry2 registry; + + static { + LOGGER.trace("Initializing query definition registry."); + ClassDefinitionParser classDefinitionParser = new ClassDefinitionParser(); + + Map map = new HashMap(); + Collection types = ClassMapper.getKnownTypes(); + for (RObjectType type : types) { + Class clazz = type.getClazz(); + if (!RObject.class.isAssignableFrom(clazz)) { + continue; + } + + Definition definition = classDefinitionParser.parseObjectTypeClass(clazz); + if (definition == null) { + continue; + } + + ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(type); + map.put(objectType.getQName(), (EntityDefinition) definition); + } + + definitions = Collections.unmodifiableMap(map); + } + + private QueryDefinitionRegistry2() { + } + + public static QueryDefinitionRegistry2 getInstance() { + if (registry == null) { + registry = new QueryDefinitionRegistry2(); + } + + return registry; + } + + @Override + public String debugDump() { + return debugDump(0); + } + + @Override + public String debugDump(int indent) { + StringBuilder builder = new StringBuilder(); + DebugUtil.indentDebugDump(builder, indent); + Collection defCollection = definitions.values(); + for (Definition definition : defCollection) { + builder.append(definition.debugDump()).append('\n'); + } + + return builder.toString(); + } + + public D findDefinition(Class type, ItemPath path, Class definitionType) { + Validate.notNull(type, "Type must not be null."); + Validate.notNull(definitionType, "Definition type must not be null."); + + EntityDefinition entityDef = definitions.get(ObjectTypes.getObjectType(type).getQName()); + return entityDef.findDefinition(path, definitionType); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java new file mode 100644 index 00000000000..3ea801c3d59 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query.RQuery; +import com.evolveum.midpoint.repo.sql.util.GetObjectResult; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.criterion.Projections; + +import java.util.Collection; + +/** + * @author lazyman + */ +public class QueryEngine2 { + + private SqlRepositoryConfiguration repoConfiguration; + private PrismContext prismContext; + + public QueryEngine2(SqlRepositoryConfiguration config, PrismContext prismContext) { + this.repoConfiguration = config; + this.prismContext = prismContext; + } + + public RQuery interpret(ObjectQuery query, Class type, + Collection> options, + boolean countingObjects, Session session) throws QueryException { + + QueryInterpreter2 interpreter = new QueryInterpreter2(repoConfiguration); + Criteria criteria = interpreter.interpret(query, type, options, prismContext, countingObjects, session); + if (countingObjects) { + criteria.setProjection(Projections.rowCount()); + } else { + criteria.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); + } + + return new RQueryCriteriaImpl(criteria); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java new file mode 100644 index 00000000000..67ac0f66757 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.matcher.DefaultMatcher; +import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; +import com.evolveum.midpoint.repo.sql.query2.matcher.PolyStringMatcher; +import com.evolveum.midpoint.repo.sql.query2.matcher.StringMatcher; +import com.evolveum.midpoint.repo.sql.query2.restriction.Restriction; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.util.ClassPathUtil; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; +import org.apache.commons.lang.reflect.ConstructorUtils; +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.ProjectionList; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; + +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl.ObjectPagingAfterOid; + +/** + * @author lazyman + */ +public class QueryInterpreter2 { + + private static final Trace LOGGER = TraceManager.getTrace(QueryInterpreter2.class); + private static final Set AVAILABLE_RESTRICTIONS; + private static final Map AVAILABLE_MATCHERS; + + static { + Set restrictions = new HashSet(); + + String packageName = Restriction.class.getPackage().getName(); + Set classes = ClassPathUtil.listClasses(packageName); + LOGGER.debug("Found {} classes in package {}.", new Object[]{classes.size(), packageName}); + for (Class clazz : classes) { + if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { + //we don't need interfaces and abstract classes + continue; + } + + if (!Restriction.class.isAssignableFrom(clazz)) { + //we don't need classes that don't inherit from Restriction + continue; + } + + try { + Restriction restriction = (Restriction) ConstructorUtils.invokeConstructor(clazz, null); + restrictions.add(restriction); + + LOGGER.debug("Added '{}' instance to available restrictions.", + new Object[]{restriction.getClass().getName()}); + } catch (Exception ex) { + LoggingUtils.logException(LOGGER, "Error occurred during query interpreter initialization", ex); + if (ex instanceof SystemException) { + throw (SystemException) ex; + } + throw new SystemException(ex.getMessage(), ex); + } + } + + AVAILABLE_RESTRICTIONS = Collections.unmodifiableSet(restrictions); + } + + static { + Map matchers = new HashMap(); + //default matcher with null key + matchers.put(null, new DefaultMatcher()); + matchers.put(PolyString.class, new PolyStringMatcher()); + matchers.put(String.class, new StringMatcher()); + + + AVAILABLE_MATCHERS = Collections.unmodifiableMap(matchers); + } + + private SqlRepositoryConfiguration repoConfiguration; + + public QueryInterpreter2(SqlRepositoryConfiguration repoConfiguration) { + this.repoConfiguration = repoConfiguration; + } + + public SqlRepositoryConfiguration getRepoConfiguration() { + return repoConfiguration; + } + + public Criteria interpret(ObjectQuery query, Class type, + Collection> options, PrismContext prismContext, + boolean countingObjects, Session session) throws QueryException { + Validate.notNull(type, "Type must not be null."); + Validate.notNull(session, "Session must not be null."); + Validate.notNull(prismContext, "Prism context must not be null."); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Interpreting query for type '{}', query:\n{}", new Object[]{type, query}); + } + + Criteria criteria; + if (query != null && query.getFilter() != null) { + criteria = interpretQuery(query, type, prismContext, session); + } else { + criteria = session.createCriteria(ClassMapper.getHQLTypeClass(type)); + } + + if (query != null && query.getPaging() instanceof ObjectPagingAfterOid) { + ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); + if (paging.getOidGreaterThan() != null) { + criteria = criteria.add(Restrictions.gt("oid", paging.getOidGreaterThan())); + } + } + + if (!countingObjects && query != null && query.getPaging() != null) { + if (query.getPaging() instanceof ObjectPagingAfterOid) { + criteria = updatePagingAndSortingByOid(criteria, query); // very special case - ascending ordering by OID (nothing more) + } else { + criteria = updatePagingAndSorting(criteria, type, query.getPaging()); + } + } + + if (!countingObjects) { + ProjectionList projections = Projections.projectionList(); + projections.add(Projections.property("fullObject")); + + projections.add(Projections.property("stringsCount")); + projections.add(Projections.property("longsCount")); + projections.add(Projections.property("datesCount")); + projections.add(Projections.property("referencesCount")); + projections.add(Projections.property("polysCount")); + projections.add(Projections.property("booleansCount")); + + criteria.setProjection(projections); + } + + return criteria; + } + + private Criteria interpretQuery(ObjectQuery query, Class type, PrismContext prismContext, + Session session) throws QueryException { + ObjectFilter filter = query.getFilter(); + try { + QueryContext2 context = new QueryContext2(this, type, query, prismContext, session); + + Criterion criterion = interpretFilter(filter, context, null); + + Criteria criteria = context.getCriteria(null); + criteria.add(criterion); + + return criteria; + } catch (QueryException ex) { + throw ex; + } catch (Exception ex) { + LOGGER.trace(ex.getMessage(), ex); + throw new QueryException(ex.getMessage(), ex); + } + } + + public Criterion interpretFilter(ObjectFilter filter, QueryContext2 context, Restriction parent) throws QueryException { + Restriction restriction = findAndCreateRestriction(filter, context, parent); + Criterion criterion = restriction.interpret(); + return criterion; + } + + public Criteria updatePagingAndSorting(Criteria query, Class type, ObjectPaging paging) { + if (paging == null) { + return query; + } + if (paging.getOffset() != null) { + query = query.setFirstResult(paging.getOffset()); + } + if (paging.getMaxSize() != null) { + query = query.setMaxResults(paging.getMaxSize()); + } + + if (paging.getDirection() == null && (paging.getOrderBy() == null || paging.getOrderBy().isEmpty())) { + return query; + } + + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + if (paging.getOrderBy() == null || paging.getOrderBy().isEmpty() || paging.getOrderBy().size() > 1 || !(paging.getOrderBy().first() instanceof NameItemPathSegment)) { + LOGGER.warn("Ordering by property path with size not equal 1 is not supported '" + paging.getOrderBy() + + "'."); + return query; + } + EntityDefinition definition = registry.findDefinition(type, null, EntityDefinition.class); + Definition def = definition.findDefinition(paging.getOrderBy(), Definition.class); + if (def == null) { + LOGGER.warn("Unknown path '" + paging.getOrderBy() + "', couldn't find definition for it, " + + "list will not be ordered by it."); + return query; + } + + String propertyName = def.getJpaName(); + if (PolyString.class.equals(def.getJaxbType())) { + propertyName += ".orig"; + } + + if (paging.getDirection() != null) { + switch (paging.getDirection()) { + case ASCENDING: + query = query.addOrder(Order.asc(propertyName)); + break; + case DESCENDING: + query = query.addOrder(Order.desc(propertyName)); + break; + } + } else { + query = query.addOrder(Order.asc(propertyName)); + } + + + return query; + } + + protected Criteria updatePagingAndSortingByOid(Criteria criteria, ObjectQuery query) { + ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); + if (paging.getOrderBy() != null || paging.getDirection() != null || paging.getOffset() != null) { + throw new IllegalArgumentException("orderBy, direction nor offset is allowed on ObjectPagingAfterOid"); + } + criteria = criteria.addOrder(Order.asc("oid")); + if (paging.getMaxSize() != null) { + criteria = criteria.setMaxResults(paging.getMaxSize()); + } + return criteria; + } + + public Matcher findMatcher(T value) { + return findMatcher(value != null ? (Class) value.getClass() : null); + } + + public Matcher findMatcher(Class type) { + Matcher matcher = AVAILABLE_MATCHERS.get(type); + if (matcher == null) { + //we return default matcher + matcher = AVAILABLE_MATCHERS.get(null); + } + + return matcher; + } + + public Restriction findAndCreateRestriction(T filter, QueryContext2 context, + Restriction parent) throws QueryException { + + for (Restriction restriction : AVAILABLE_RESTRICTIONS) { + Restriction res = restriction.newInstance(); + res.setContext(context); + if (!res.canHandle(filter)) { + continue; + } + res.setParent(parent); + res.setFilter(filter); + + return res; + } + + LOGGER.error("Couldn't find proper restriction that can handle filter '{}'.", new Object[]{filter.debugDump()}); + throw new QueryException("Couldn't find proper restriction that can handle '" + filter + "'"); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java new file mode 100644 index 00000000000..06844423ed5 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.repo.sql.query.RQuery; +import org.apache.commons.lang.Validate; +import org.hibernate.Criteria; +import org.hibernate.HibernateException; +import org.hibernate.ScrollMode; +import org.hibernate.ScrollableResults; + +import java.util.List; + +/** + * @author lazyman + */ +public class RQueryCriteriaImpl implements RQuery { + + private Criteria criteria; + + public RQueryCriteriaImpl(Criteria criteria) { + Validate.notNull(criteria, "Criteria must not be null."); + this.criteria = criteria; + } + + @Override + public List list() throws HibernateException { + return criteria.list(); + } + + @Override + public Object uniqueResult() throws HibernateException { + return criteria.uniqueResult(); + } + + @Override + public ScrollableResults scroll(ScrollMode mode) throws HibernateException { + return criteria.scroll(mode); + } + + public Criteria getCriteria() { + return criteria; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryImpl.java new file mode 100644 index 00000000000..c2b7c4feac9 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.repo.sql.query.RQuery; +import org.apache.commons.lang.Validate; +import org.hibernate.HibernateException; +import org.hibernate.ScrollMode; +import org.hibernate.ScrollableResults; + +import java.util.List; + +/** + * @author lazyman + */ +public class RQueryImpl implements RQuery { + + private org.hibernate.Query query; + + public RQueryImpl(org.hibernate.Query query) { + Validate.notNull(query, "Query must not be null."); + this.query = query; + } + + @Override + public List list() throws HibernateException { + return query.list(); + } + + @Override + public Object uniqueResult() throws HibernateException { + return query.uniqueResult(); + } + + @Override + public ScrollableResults scroll(ScrollMode mode) throws HibernateException { + return query.scroll(mode); + } + + public org.hibernate.Query getQuery() { + return query; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java new file mode 100644 index 00000000000..75eae84cc6c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Any { + + String jaxbNameNamespace() default SchemaConstantsGenerated.NS_COMMON; + + String jaxbNameLocalPart(); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java new file mode 100644 index 00000000000..d88d581e339 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class AnyDefinition extends Definition { + + public AnyDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { + super(jaxbName, jaxbType, jpaName, jpaType); + } + + @Override + protected String getDebugDumpClassName() { + return "Any"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java new file mode 100644 index 00000000000..903e8be87f8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.any.RAssignmentExtension; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.StringUtils; +import org.hibernate.annotations.Index; + +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Enumerated; +import javax.persistence.Lob; +import javax.persistence.Transient; +import javax.xml.namespace.QName; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.util.Set; + +/** + * @author lazyman + */ +public class ClassDefinitionParser { + + private static final Trace LOGGER = TraceManager.getTrace(ClassDefinitionParser.class); + + public EntityDefinition parseObjectTypeClass(Class type) { + ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(type); + QName jaxbName = objectType.getQName(); + Class jaxbType = objectType.getClassDefinition(); + + EntityDefinition entityDefinition = new EntityDefinition(jaxbName, jaxbType, type.getSimpleName(), type); + updateEntityDefinition(entityDefinition); + + return entityDefinition; + } + + private void updateEntityDefinition(EntityDefinition entity) { + LOGGER.trace("### {}", new Object[]{entity.getJpaName()}); + addVirtualDefinitions(entity); + Method[] methods = entity.getJpaType().getMethods(); + + entity.setEmbedded(entity.getJpaType().getAnnotation(Embeddable.class) != null); + + for (Method method : methods) { + String methodName = method.getName(); + if (Modifier.isStatic(method.getModifiers()) || "getClass".equals(methodName) || + !methodName.startsWith("is") && !methodName.startsWith("get")) { + //it's not getter for property + continue; + } + + if (method.isAnnotationPresent(Transient.class)) { + continue; + } + + LOGGER.trace("# {}", new Object[]{methodName}); + + QName jaxbName = getJaxbName(method); + Class jaxbType = getJaxbType(method); + String jpaName = getJpaName(method); + Definition definition = createDefinition(jaxbName, jaxbType, jpaName, method); + entity.addDefinition(definition); + } + } + + private void addVirtualDefinitions(EntityDefinition entityDef) { + Class jpaType = entityDef.getJpaType(); + addVirtualDefinitionsForClass(entityDef, jpaType); + + while ((jpaType = jpaType.getSuperclass()) != null) { + addVirtualDefinitionsForClass(entityDef, jpaType); + } + } + + private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpaType) { + if (!jpaType.isAnnotationPresent(QueryEntity.class)) { + return; + } + + QueryEntity qEntity = (QueryEntity) jpaType.getAnnotation(QueryEntity.class); + for (VirtualProperty property : qEntity.properties()) { + QName jaxbName = createQName(property.jaxbName()); + VirtualPropertyDefinition def = new VirtualPropertyDefinition(jaxbName, property.jaxbType(), + property.jpaName(), property.jpaType()); + def.setAdditionalParams(property.additionalParams()); + entityDef.addDefinition(def); + } + + for (VirtualReference reference : qEntity.references()) { + + } + + for (VirtualCollection collection : qEntity.collections()) { + QName jaxbName = createQName(collection.jaxbName()); + + VirtualCollectionDefinition def = new VirtualCollectionDefinition(jaxbName, + collection.jaxbType(), collection.jpaName(), collection.jpaType()); + def.setAdditionalParams(collection.additionalParams()); + updateCollectionDefinition(def, collection.collectionType(), jaxbName, collection.jpaName()); + + entityDef.addDefinition(def); + } + } + + private QName createQName(JaxbName name) { + return new QName(name.namespace(), name.localPart()); + } + + private Definition createDefinition(QName jaxbName, Class jaxbType, String jpaName, AnnotatedElement object) { + Class jpaType = (object instanceof Class) ? (Class) object : ((Method) object).getReturnType(); + + Definition definition; + if (ObjectReference.class.isAssignableFrom(jpaType)) { + ReferenceDefinition refDef = new ReferenceDefinition(jaxbName, jaxbType, jpaName, jpaType); + definition = updateReferenceDefinition(refDef, object); + } else if (RAssignmentExtension.class.isAssignableFrom(jpaType)) { + definition = new AnyDefinition(jaxbName, jaxbType, jpaName, jpaType); + } else if (Set.class.isAssignableFrom(jpaType)) { + CollectionDefinition collDef = new CollectionDefinition(jaxbName, jaxbType, jpaName, jpaType); + updateCollectionDefinition(collDef, object, null, null); + definition = collDef; + } else if (isEntity(object)) { + EntityDefinition entityDef = new EntityDefinition(jaxbName, jaxbType, jpaName, jpaType); + if ("com.evolveum.midpoint.repo.sql.data.common.embedded".equals(jpaType.getPackage().getName())) { + updateEntityDefinition(entityDef); + } + definition = entityDef; + } else { + PropertyDefinition propDef = new PropertyDefinition(jaxbName, jaxbType, jpaName, jpaType); + definition = updatePropertyDefinition(propDef, object); + } + + return definition; + } + + private CollectionDefinition updateCollectionDefinition(CollectionDefinition definition, AnnotatedElement object, + QName jaxbName, String jpaName) { + Definition collDef; + if (object instanceof Method) { + Method method = (Method) object; + ParameterizedType type = (ParameterizedType) method.getGenericReturnType(); + Class clazz = (Class) type.getActualTypeArguments()[0]; + + QName realJaxbName = getJaxbName(method); + Class jaxbType = getJaxbType(clazz); + String realJpaName = getJpaName(method); + collDef = createDefinition(realJaxbName, jaxbType, realJpaName, clazz); + } else { + Class clazz = (Class) object; + + Class jaxbType = getJaxbType(clazz); + collDef = createDefinition(jaxbName, jaxbType, jpaName, clazz); + } + + if (collDef instanceof EntityDefinition) { + updateEntityDefinition((EntityDefinition) collDef); + } + + definition.setDefinition(collDef); + + return definition; + } + + private boolean isEntity(AnnotatedElement object) { + Class type = (object instanceof Class) ? (Class) object : ((Method) object).getReturnType(); + if (RPolyString.class.isAssignableFrom(type)) { + //it's hibernate entity but from prism point of view it's property + return false; + } + + return type.getAnnotation(Entity.class) != null || type.getAnnotation(Embeddable.class) != null; + } + + private PropertyDefinition updatePropertyDefinition(PropertyDefinition definition, AnnotatedElement object) { + if (object.isAnnotationPresent(Lob.class)) { + definition.setLob(true); + } + + if (object.isAnnotationPresent(Enumerated.class)) { + definition.setEnumerated(true); + } + + //todo implement also lookup for @Table indexes + if (object.isAnnotationPresent(Index.class)) { + definition.setIndexed(true); + } + + return definition; + } + + private ReferenceDefinition updateReferenceDefinition(ReferenceDefinition definition, AnnotatedElement object) { + if (object.isAnnotationPresent(Embedded.class)) { + definition.setEmbedded(true); + } + + return definition; + } + + private QName getJaxbName(Method method) { + QName name = new QName(SchemaConstantsGenerated.NS_COMMON, getPropertyName(method.getName())); + if (method.isAnnotationPresent(JaxbName.class)) { + JaxbName jaxbName = method.getAnnotation(JaxbName.class); + name = new QName(jaxbName.namespace(), jaxbName.localPart()); + } + + return name; + } + + private Class getJaxbType(Method method) { + return getJaxbType(method.getReturnType()); + } + + private Class getJaxbType(Class clazz) { + if (RObject.class.isAssignableFrom(clazz)) { + ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(clazz); + return objectType.getClassDefinition(); + } + + if (clazz.getAnnotation(JaxbType.class) != null) { + JaxbType type = (JaxbType) clazz.getAnnotation(JaxbType.class); + return type.type(); + } + + return clazz; + } + + private String getJpaName(Method method) { + String methodName = method.getName(); + return getPropertyName(methodName); + } + + private String getPropertyName(String methodName) { + int startIndex = 3; //method name starts with "get" + if (methodName.startsWith("is")) { + startIndex = 2; + } + + char first = Character.toLowerCase(methodName.charAt(startIndex)); + return Character.toString(first) + StringUtils.substring(methodName, startIndex + 1, methodName.length()); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java new file mode 100644 index 00000000000..c63edbcb7f3 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.util.DebugDumpable; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class CollectionDefinition extends Definition { + + private Definition definition; + + public CollectionDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { + super(jaxbName, jaxbType, propertyName, propertyType); + } + + public Definition getDefinition() { + return definition; + } + + void setDefinition(Definition definition) { + this.definition = definition; + } + + @Override + protected void toStringExtended(StringBuilder builder) { + String def = definition != null ? definition.toString() : null; + builder.append(", def=").append(def); + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < indent; i++) { + sb.append(DebugDumpable.INDENT_STRING); + } + sb.append(toString()); + + sb.append('\n'); + String def = null; + if (definition == null) { + for (int i = 0; i < indent + 1; i++) { + sb.append(DebugDumpable.INDENT_STRING); + } + } else { + def = definition.debugDump(indent + 1); + } + sb.append(def); + + return sb.toString(); + } + + @Override + protected String getDebugDumpClassName() { + return "Col"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java new file mode 100644 index 00000000000..873aec73e64 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.DebugDumpable; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public abstract class Definition implements DebugDumpable { + + //jaxb + private QName jaxbName; + private Class jaxbType; + //jpa + private String jpaName; + private Class jpaType; + + public Definition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { + this.jaxbName = jaxbName; + this.jaxbType = jaxbType; + this.jpaName = jpaName; + this.jpaType = jpaType; + } + + public QName getJaxbName() { + return jaxbName; + } + + public Class getJaxbType() { + return jaxbType; + } + + public String getJpaName() { + return jpaName; + } + + public Class getJpaType() { + return jpaType; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(getDebugDumpClassName()); + builder.append('{'); + builder.append("jaxbN=").append(dumpQName(jaxbName)); + builder.append(", jaxbT=").append((jaxbType != null ? jaxbType.getSimpleName() : "")); + builder.append(", jpaN=").append(jpaName); + builder.append(", jpaT=").append((jpaType != null ? jpaType.getSimpleName() : "")); + toStringExtended(builder); + builder.append('}'); + + return builder.toString(); + } + + protected void toStringExtended(StringBuilder builder) { + + } + + protected String dumpQName(QName qname) { + if (qname == null) { + return null; + } + + String namespace = qname.getNamespaceURI(); + namespace = namespace.replaceFirst("http://midpoint\\.evolveum\\.com/xml/ns/public", ".."); + + StringBuilder builder = new StringBuilder(); + builder.append('{'); + builder.append(namespace); + builder.append('}'); + builder.append(qname.getLocalPart()); + return builder.toString(); + } + + @Override + public String debugDump() { + return debugDump(0); + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < indent; i++) { + sb.append(DebugDumpable.INDENT_STRING); + } + sb.append(toString()); + return sb.toString(); + } + + /** + * Return a human readable name of this class suitable for logs. + */ + protected abstract String getDebugDumpClassName(); + + public D findDefinition(ItemPath path, Class type) { + return null; + } + + public D findDefinition(QName jaxbName, Class type) { + return null; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java new file mode 100644 index 00000000000..15dd2fbf1ad --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.util.Comparator; + +/** + * @author lazyman + */ +public class DefinitionComparator implements Comparator { + + @Override + public int compare(Definition o1, Definition o2) { + if (o1.getClass().equals(o2.getClass())) { + return String.CASE_INSENSITIVE_ORDER.compare(o1.getJaxbName().getLocalPart(), + o2.getJaxbName().getLocalPart()); + } + + return getType(o1) - getType(o2); + } + + private int getType(Definition def) { + if (def == null) { + return 0; + } + + if (def instanceof PropertyDefinition) { + return 1; + } else if (def instanceof ReferenceDefinition) { + return 2; + } else if (def instanceof CollectionDefinition) { + return 3; + } else if (def instanceof AnyDefinition) { + return 4; + } else if (def instanceof EntityDefinition) { + return 5; + } + + return 0; + } +} \ No newline at end of file diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java new file mode 100644 index 00000000000..a9e52d160b8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author lazyman + */ +public class EntityDefinition extends Definition { + + /** + * child definitions of this entity + */ + private List definitions; + private boolean embedded; + + public EntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { + super(jaxbName, jaxbType, jpaName, jpaType); + } + + public boolean isEmbedded() { + return embedded; + } + + void setEmbedded(boolean embedded) { + this.embedded = embedded; + } + + public List getDefinitions() { + if (definitions == null) { + definitions = new ArrayList(); + } + + return Collections.unmodifiableList(definitions); + } + + public void addDefinition(Definition definition) { + if (definitions == null) { + definitions = new ArrayList(); + } + + Definition oldDef = findDefinition(definition.getJaxbName(), Definition.class); + if (oldDef != null) { + definitions.remove(oldDef); + } + definitions.add(definition); + + Collections.sort(definitions, new DefinitionComparator()); + } + + @Override + protected void toStringExtended(StringBuilder builder) { + builder.append(", embedded=").append(isEmbedded()); + builder.append(", definitions=["); + + List definitions = getDefinitions(); + for (Definition definition : definitions) { + builder.append(definition.getDebugDumpClassName()); + builder.append('(').append(dumpQName(definition.getJaxbName())).append(')'); + } + builder.append(']'); + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < indent; i++) { + sb.append(DebugDumpable.INDENT_STRING); + } + sb.append(toString()); + + List definitions = getDefinitions(); + for (Definition definition : definitions) { + sb.append(definition.debugDump(indent + 1)); + if (definitions.indexOf(definition) != definitions.size() - 1) { + sb.append('\n'); + } + } + + return sb.toString(); + } + + @Override + protected String getDebugDumpClassName() { + return "Ent"; + } + + @Override + public D findDefinition(ItemPath path, Class type) { + if (path == null || path.isEmpty()) { + if (type.isAssignableFrom(EntityDefinition.class)) { + return (D) this; + } + } + + NameItemPathSegment first = (NameItemPathSegment) path.first(); + ItemPath tail = path.tail(); + if (ObjectType.F_METADATA.equals(first.getName())) { + //metadata is not an repository entity + first = (NameItemPathSegment) tail.first(); + tail = tail.tail(); + } else if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, first.getName()) && + tail != null && + tail.first() instanceof NameItemPathSegment && + QNameUtil.match(ConstructionType.F_RESOURCE_REF, ((NameItemPathSegment) (tail.first())).getName())) { + // ugly hack: construction/resourceRef -> resourceRef + first = (NameItemPathSegment) tail.first(); + tail = tail.tail(); + } + + if (tail.isEmpty()) { + return findDefinition(first.getName(), type); + } else { + Definition def = findDefinition(first.getName(), Definition.class); + if (def instanceof CollectionDefinition) { + CollectionDefinition collDef = (CollectionDefinition) def; + def = collDef.getDefinition(); + } + + if (def instanceof EntityDefinition) { + EntityDefinition nextEntity = (EntityDefinition) def; + return nextEntity.findDefinition(tail, type); + } + } + + return null; + } + + @Override + public D findDefinition(QName jaxbName, Class type) { + Validate.notNull(jaxbName, "Jaxb name must not be null."); + Validate.notNull(type, "Definition type must not be null."); + + for (Definition definition : getDefinitions()) { + //TODO: using match instead of strict equals..is this OK for repository??this is the situation, we have "common" namepsace + if (!QNameUtil.match(jaxbName, definition.getJaxbName())){ + continue; + } +// if (!jaxbName.equals(definition.getJaxbName())) { +// continue; +// } + + if (type.isAssignableFrom(definition.getClass())) { + return (D) definition; + } + } + + return null; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java new file mode 100644 index 00000000000..3576bf70db8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * @author lazyman + */ +@Target({TYPE, METHOD, FIELD}) +@Retention(RUNTIME) +public @interface JaxbName { + + String namespace() default SchemaConstantsGenerated.NS_COMMON; + + String localPart(); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java new file mode 100644 index 00000000000..e2cec2dff58 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * @author lazyman + */ +@Target({TYPE, METHOD, FIELD}) +@Retention(RUNTIME) +public @interface JaxbType { + + Class type(); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java new file mode 100644 index 00000000000..3f069afff6a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class PropertyDefinition extends Definition { + + //jpa special types + private boolean lob; + private boolean enumerated; + //jpa special things + private boolean indexed; + + public PropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { + super(jaxbName, jaxbType, propertyName, propertyType); + } + + public boolean isLob() { + return lob; + } + + public boolean isPolyString() { + return RPolyString.class.equals(getJpaType()); + } + + public boolean isEnumerated() { + return enumerated; + } + + public boolean isIndexed() { + return indexed; + } + + void setLob(boolean lob) { + this.lob = lob; + } + + void setEnumerated(boolean enumerated) { + this.enumerated = enumerated; + } + + void setIndexed(boolean indexed) { + this.indexed = indexed; + } + + @Override + protected void toStringExtended(StringBuilder builder) { + builder.append(", lob=").append(isLob()); + builder.append(", enumerated=").append(isEnumerated()); + builder.append(", indexed=").append(isIndexed()); + } + + @Override + protected String getDebugDumpClassName() { + return "Prop"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java new file mode 100644 index 00000000000..8561e1d6b57 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface QueryEntity { + + JaxbName jaxbName() default @JaxbName(localPart = ""); + + Class jaxbType() default Object.class; + + VirtualProperty[] properties() default {}; + + VirtualCollection[] collections() default {}; + + VirtualEntity[] entities() default {}; + + VirtualReference[] references() default {}; +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java new file mode 100644 index 00000000000..f987ade55ec --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class ReferenceDefinition extends Definition { + + private boolean embedded; + + public ReferenceDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { + super(jaxbName, jaxbType, jpaName, jpaType); + } + + public boolean isEmbedded() { + return embedded; + } + + void setEmbedded(boolean embedded) { + this.embedded = embedded; + } + + @Override + protected void toStringExtended(StringBuilder builder) { + builder.append(", embedded=").append(isEmbedded()); + } + + @Override + protected String getDebugDumpClassName() { + return "Ref"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java new file mode 100644 index 00000000000..5c3ebd02624 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface VirtualCollection { + + JaxbName jaxbName(); + + Class jaxbType(); + + String jpaName(); + + Class jpaType(); + + VirtualQueryParam[] additionalParams() default {}; + + Class collectionType(); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java new file mode 100644 index 00000000000..fca23badb2c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class VirtualCollectionDefinition extends CollectionDefinition { + + private VirtualQueryParam[] additionalParams; + + public VirtualCollectionDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { + super(jaxbName, jaxbType, propertyName, propertyType); + } + + public VirtualQueryParam[] getAdditionalParams() { + return additionalParams; + } + + void setAdditionalParams(VirtualQueryParam[] additionalParams) { + this.additionalParams = additionalParams; + } + + @Override + protected void toStringExtended(StringBuilder builder) { + super.toStringExtended(builder); + + builder.append(", params=").append(additionalParams.length); + } + + @Override + protected String getDebugDumpClassName() { + return "VirtualCol"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java new file mode 100644 index 00000000000..de17e64c894 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.io.Serializable; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface VirtualEntity { + + JaxbName jaxbName(); + + Class jaxbType(); + + String jpaName(); + + Class jpaType(); + + VirtualQueryParam[] additionalParams() default {}; +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java new file mode 100644 index 00000000000..9a4c545575f --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class VirtualEntityDefinition extends EntityDefinition { + + private VirtualQueryParam[] additionalParams; + + public VirtualEntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { + super(jaxbName, jaxbType, jpaName, jpaType); + } + + public VirtualQueryParam[] getAdditionalParams() { + return additionalParams; + } + + void setAdditionalParams(VirtualQueryParam[] additionalParams) { + this.additionalParams = additionalParams; + } + + @Override + protected void toStringExtended(StringBuilder builder) { + super.toStringExtended(builder); + + builder.append(", params=").append(additionalParams.length); + } + + @Override + protected String getDebugDumpClassName() { + return "VirtualEnt"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java new file mode 100644 index 00000000000..0ce2fbf4b99 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.io.Serializable; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface VirtualProperty { + + JaxbName jaxbName(); + + Class jaxbType(); + + String jpaName(); + + Class jpaType(); + + VirtualQueryParam[] additionalParams() default {}; +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java new file mode 100644 index 00000000000..4f475d5a984 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class VirtualPropertyDefinition extends PropertyDefinition { + + private VirtualQueryParam[] additionalParams; + + public VirtualPropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { + super(jaxbName, jaxbType, propertyName, propertyType); + } + + public VirtualQueryParam[] getAdditionalParams() { + return additionalParams; + } + + void setAdditionalParams(VirtualQueryParam[] additionalParams) { + this.additionalParams = additionalParams; + } + + @Override + protected void toStringExtended(StringBuilder builder) { + super.toStringExtended(builder); + + builder.append(", params=").append(additionalParams.length); + } + + @Override + protected String getDebugDumpClassName() { + return "VirtualProp"; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java new file mode 100644 index 00000000000..66440282424 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.io.Serializable; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface VirtualQueryParam { + + String name(); + + Class type(); + + String value(); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java new file mode 100644 index 00000000000..f20fda0a1db --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.io.Serializable; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author lazyman + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface VirtualReference { + + JaxbName jaxbName(); + + Class jaxbType(); + + String jpaName(); + + Class jpaType(); + + VirtualQueryParam[] additionalParams() default {}; +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java new file mode 100644 index 00000000000..7d18750cbbf --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.matcher; + +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; +import org.hibernate.criterion.Criterion; + +/** + * @author lazyman + */ +public class DefaultMatcher extends Matcher { + + @Override + public Criterion match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) + throws QueryException { + + return basicMatch(operation, propertyName, value, false); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java new file mode 100644 index 00000000000..dac655a0ce4 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.matcher; + +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.MatchMode; +import org.hibernate.criterion.Restrictions; +import org.hibernate.criterion.SimpleExpression; + +/** + * @author lazyman + */ +public abstract class Matcher { + + /** + * Create hibernate {@link Criterion} based on matcher defined in filter. + * + * @param operation + * @param propertyName + * @param value + * @param matcher Now type of {@link String}, but will be updated to {@link javax.xml.namespace.QName} + * type after query-api update + * @return + * @throws QueryException + */ + public abstract Criterion match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) + throws QueryException; + + protected Criterion basicMatch(ItemRestrictionOperation operation, String propertyName, Object value, + boolean ignoreCase) throws QueryException { + Criterion criterion; + switch (operation) { + case EQ: + if (value == null) { + criterion = Restrictions.isNull(propertyName); + } else { + criterion = Restrictions.eq(propertyName, value); + } + break; + case GT: + criterion = Restrictions.gt(propertyName, value); + break; + case GE: + criterion = Restrictions.ge(propertyName, value); + break; + case LT: + criterion = Restrictions.lt(propertyName, value); + break; + case LE: + criterion = Restrictions.le(propertyName, value); + break; + case NOT_NULL: + criterion = Restrictions.isNotNull(propertyName); + break; + case NULL: + criterion = Restrictions.isNull(propertyName); + break; + case STARTS_WITH: + criterion = Restrictions.like(propertyName, (String) value, MatchMode.START); + break; + case ENDS_WITH: + criterion = Restrictions.like(propertyName, (String) value, MatchMode.END); + break; + case SUBSTRING: + criterion = Restrictions.like(propertyName, (String) value, MatchMode.ANYWHERE); + break; + default: + throw new QueryException("Unknown operation '" + operation + "'."); + } + + if (ignoreCase && (value instanceof String) && (criterion instanceof SimpleExpression)) { + criterion = ((SimpleExpression) criterion).ignoreCase(); + } + + return criterion; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java new file mode 100644 index 00000000000..2d02728905a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.matcher; + +import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule; +import com.evolveum.midpoint.prism.match.PolyStringOrigMatchingRule; +import com.evolveum.midpoint.prism.match.PolyStringStrictMatchingRule; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; +import org.apache.commons.lang.StringUtils; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +/** + * @author lazyman + */ +public class PolyStringMatcher extends Matcher { + + //todo will be changed to QNames later (after query api update) + public static final String STRICT = PolyStringStrictMatchingRule.NAME.getLocalPart(); + public static final String ORIG = PolyStringOrigMatchingRule.NAME.getLocalPart(); + public static final String NORM = PolyStringNormMatchingRule.NAME.getLocalPart(); + + public static final String STRICT_IGNORE_CASE = "strictIgnoreCase"; + public static final String ORIG_IGNORE_CASE = "origIgnoreCase"; + public static final String NORM_IGNORE_CASE = "normIgnoreCase"; + + @Override + public Criterion match(ItemRestrictionOperation operation, String propertyName, PolyString value, String matcher) + throws QueryException { + + boolean ignoreCase = STRICT_IGNORE_CASE.equals(matcher) + || ORIG_IGNORE_CASE.equals(matcher) + || NORM_IGNORE_CASE.equals(matcher); + + if (StringUtils.isEmpty(matcher) + || STRICT.equals(matcher) || STRICT_IGNORE_CASE.equals(matcher)) { + Conjunction conjunction = Restrictions.conjunction(); + conjunction.add(createOrigMatch(operation, propertyName, value, ignoreCase)); + conjunction.add(createNormMatch(operation, propertyName, value, ignoreCase)); + + return conjunction; + } else if (ORIG.equals(matcher) || ORIG_IGNORE_CASE.equals(matcher)) { + return createOrigMatch(operation, propertyName, value, ignoreCase); + } else if (NORM.equals(matcher) || NORM_IGNORE_CASE.equals(matcher)) { + return createNormMatch(operation, propertyName, value, ignoreCase); + } else { + throw new QueryException("Unknown matcher '" + matcher + "'."); + } + } + + private Criterion createNormMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, + boolean ignoreCase) throws QueryException { + + String realValue = value != null ? value.getNorm() : null; + return basicMatch(operation, propertyName + '.' + RPolyString.F_NORM, realValue, ignoreCase); + } + + private Criterion createOrigMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, + boolean ignoreCase) throws QueryException { + + String realValue = value != null ? value.getOrig() : null; + return basicMatch(operation, propertyName + '.' + RPolyString.F_ORIG, realValue, ignoreCase); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java new file mode 100644 index 00000000000..c9bb925a1a8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.matcher; + +import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; +import org.hibernate.criterion.Criterion; + +/** + * @author lazyman + */ +public class StringMatcher extends Matcher { + + //todo will be changed to QName later (after query api update) + public static final String IGNORE_CASE = StringIgnoreCaseMatchingRule.NAME.getLocalPart(); + + @Override + public Criterion match(ItemRestrictionOperation operation, String propertyName, String value, String matcher) + throws QueryException { + + boolean ignoreCase = IGNORE_CASE.equalsIgnoreCase(matcher); + + return basicMatch(operation, propertyName, value, ignoreCase); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java new file mode 100644 index 00000000000..ad37a9eb539 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +/** + * @author lazyman + */ +public class AndRestriction extends NaryLogicalRestriction { + + @Override + public boolean canHandle(ObjectFilter filter) { + if (!super.canHandle(filter)) { + return false; + } + + return (filter instanceof AndFilter); + } + + @Override + public Criterion interpret() throws QueryException { + validateFilter(filter); + Conjunction conjunction = Restrictions.conjunction(); + updateJunction(filter.getConditions(), conjunction); + + return conjunction; + } + + @Override + public AndRestriction newInstance() { + return new AndRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java new file mode 100644 index 00000000000..96cefb91655 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyConverter; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.List; + +/** + * @author lazyman + */ +public class AnyPropertyRestriction extends ItemRestriction { + + private static final Trace LOGGER = TraceManager.getTrace(AnyPropertyRestriction.class); + + @Override + public boolean canHandle(ObjectFilter filter) throws QueryException { + if (!super.canHandle(filter)) { + return false; + } + + ValueFilter valFilter = (ValueFilter) filter; + ItemPath fullPath = valFilter.getFullPath(); + + List defPath = createDefinitionPath(fullPath); + return containsAnyDefinition(defPath) + || (fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION))) + || (fullPath.first().equivalent(new NameItemPathSegment(ShadowType.F_ATTRIBUTES))); + } + + private boolean containsAnyDefinition(List definitions) { + for (Definition definition : definitions) { + if (definition instanceof AnyDefinition) { + return true; + } + } + + return false; + } + + @Override + public Criterion interpretInternal(ValueFilter filter) throws QueryException { + + ItemDefinition itemDefinition = filter.getDefinition(); + QName name = itemDefinition.getName(); + QName type = itemDefinition.getTypeName(); + + if (name == null || type == null) { + throw new QueryException("Couldn't get name or type for queried item '" + itemDefinition + "'"); + } + + ItemPath anyItemPath = createAnyItemPath(filter.getParentPath(), filter.getDefinition()); + if (!getContext().hasAlias(anyItemPath)) { + QName anyTypeName = ((NameItemPathSegment) anyItemPath.last()).getName(); + LOGGER.trace("Condition item is from 'any' container, adding new criteria based on any type '{}'", + new Object[]{anyTypeName.getLocalPart()}); + addNewCriteriaToContext(anyItemPath, null, anyTypeName.getLocalPart()); + } + String propertyNamePrefix = getContext().getAlias(anyItemPath) + '.'; + + Conjunction conjunction = Restrictions.conjunction(); + + RObjectExtensionType ownerType = filter.getFullPath().first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) ? + RObjectExtensionType.EXTENSION : RObjectExtensionType.ATTRIBUTES; + conjunction.add(Restrictions.eq(propertyNamePrefix + "ownerType", ownerType)); + + conjunction.add(Restrictions.eq(propertyNamePrefix + RAnyValue.F_NAME, RUtil.qnameToString(name))); + + Object testedValue = getValue(((PropertyValueFilter) filter).getValues()); + Object value = RAnyConverter.getAggregatedRepoObject(testedValue); + conjunction.add(createCriterion(propertyNamePrefix + RAnyValue.F_VALUE, value, filter)); + + // todo what about "not"? but it would not work in this setting anyway (ownerType=A & name=B & value=C) + //conjunction.add(Restrictions.isNotNull(propertyNamePrefix + RAnyValue.F_VALUE)); + return conjunction; + } + + private ItemPath createAnyItemPath(ItemPath path, ItemDefinition itemDef) throws QueryException { + try { + List segments = new ArrayList(); +// segments.addAll(path.getSegments()); + // get any type name (e.g. clobs, strings, dates,...) based on definition + String anyTypeName = RAnyConverter.getAnySetType(itemDef); + segments.add(new NameItemPathSegment(new QName(RUtil.NS_SQL_REPO, anyTypeName))); + + return new ItemPath(segments); + } catch (SchemaException ex) { + throw new QueryException(ex.getMessage(), ex); + } + } + + @Override + public AnyPropertyRestriction newInstance() { + return new AnyPropertyRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java new file mode 100644 index 00000000000..977cde61d76 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import org.hibernate.criterion.Criterion; + +/** + * @author lazyman + */ +public class CollectionRestriction extends ItemRestriction { + + @Override + public boolean canHandle(ObjectFilter filter) throws QueryException { + if (!super.canHandle(filter)) { + return false; + } + + ValueFilter valFilter = (ValueFilter) filter; + ItemPath fullPath = valFilter.getFullPath(); + + CollectionDefinition def = findProperDefinition(fullPath, CollectionDefinition.class); + if (def == null) { + return false; + } + + return def.getDefinition() instanceof PropertyDefinition; + } + + @Override + public Criterion interpretInternal(ValueFilter filter) throws QueryException { + ItemPath fullPath = filter.getFullPath(); + QueryContext2 context = getContext(); + CollectionDefinition def = findProperDefinition(fullPath, CollectionDefinition.class); + + String alias = context.getAlias(fullPath); + Object value = getValueFromFilter(filter, (PropertyDefinition) def.getDefinition()); + + // TODO what about not-null ? + + //custom propertyPath handling for PolyString (it's embedded entity, not a primitive) + if (value instanceof PolyString) { + return createCriterion(alias, value, filter); + } + + return createCriterion(alias + ".elements", value, filter); + } + + @Override + public Restriction newInstance() { + return new CollectionRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java new file mode 100644 index 00000000000..1daba227639 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.InOidFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +/** + * @author lazyman + */ +public class InOidRestriction extends Restriction { + + @Override + public Criterion interpret() throws QueryException { + String property = getContext().getAlias(null) + ".oid"; + + return Restrictions.in(property, filter.getOids()); + } + + @Override + public boolean canHandle(ObjectFilter filter) throws QueryException { + if (filter instanceof InOidFilter) { + return true; + } + + return false; + } + + @Override + public Restriction newInstance() { + return new InOidRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java new file mode 100644 index 00000000000..79e8c8ce476 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.EqualFilter; +import com.evolveum.midpoint.prism.query.GreaterFilter; +import com.evolveum.midpoint.prism.query.LessFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; +import com.evolveum.midpoint.prism.query.SubstringFilter; +import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.QueryDefinitionRegistry2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualQueryParam; +import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.apache.commons.lang.Validate; +import org.hibernate.Criteria; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; +import org.hibernate.sql.JoinType; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author lazyman + */ +public abstract class ItemRestriction extends Restriction { + + private static final Trace LOGGER = TraceManager.getTrace(ItemRestriction.class); + + @Override + public boolean canHandle(ObjectFilter filter) throws QueryException { + Validate.notNull(filter, "Object filter must not be null."); + if (!(filter instanceof ValueFilter)) { + return false; + } + return true; + } + + @Override + public Criterion interpret() throws QueryException { + + ItemPath path = filter.getFullPath(); + if (path != null) { + // at first we build criterias with aliases + updateQueryContext(path); + } + + Criterion main = interpretInternal(filter); + Criterion virtual = createVirtualCriterion(path); + if (virtual != null) { + return Restrictions.and(virtual, main); + } + + return main; + } + + public abstract Criterion interpretInternal(T filter) throws QueryException; + + private TypeRestriction findTypeRestrictionParent(Restriction restriction) { + if (restriction == null) { + return null; + } + + if (restriction instanceof TypeRestriction) { + return (TypeRestriction) restriction; + } + + return findTypeRestrictionParent(restriction.getParent()); + } + + private Set> findOtherPossibleParents() { + TypeRestriction typeRestriction = findTypeRestrictionParent(this); + ObjectTypes typeClass; + if (typeRestriction != null) { + TypeFilter filter = typeRestriction.getFilter(); + typeClass = ObjectTypes.getObjectTypeFromTypeQName(filter.getType()); + } else { + typeClass = ObjectTypes.getObjectType(getContext().getType()); + } + + Set> classes = new HashSet<>(); + classes.add(typeClass.getClassDefinition()); + + switch (typeClass) { + case OBJECT: + classes.addAll(ObjectTypes.getAllObjectTypes()); + break; + case FOCUS_TYPE: + classes.add(UserType.class); + case ABSTRACT_ROLE: + classes.add(RoleType.class); + classes.add(OrgType.class); + } + + LOGGER.trace("Found possible parents {} for entity definitions.", Arrays.toString(classes.toArray())); + return classes; + } + + protected T findProperDefinition(ItemPath path, Class clazz) { + QueryContext2 context = getContext(); + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + if (!ObjectType.class.equals(context.getType())) { + return registry.findDefinition(context.getType(), path, clazz); + } + + //we should try to find property in descendant classes + for (Class type : findOtherPossibleParents()) { + Definition def = registry.findDefinition(type, path, clazz); + if (def != null) { + return (T) def; + } + } + + return null; + } + + protected EntityDefinition findProperEntityDefinition(ItemPath path) { + QueryContext2 context = getContext(); + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + if (!ObjectType.class.equals(context.getType())) { + return registry.findDefinition(context.getType(), null, EntityDefinition.class); + } + + EntityDefinition entity = null; + // we should try to find property in descendant classes + for (Class type : findOtherPossibleParents()) { + entity = registry.findDefinition(type, null, EntityDefinition.class); + Definition def = entity.findDefinition(path, Definition.class); + if (def != null) { + break; + } + } + LOGGER.trace("Found proper entity definition for path {}, {}", path, entity.toString()); + return entity; + } + + //todo reimplement, use DefinitionHandlers or maybe another great concept + private void updateQueryContext(ItemPath path) throws QueryException { + LOGGER.trace("Updating query context based on path {}", new Object[]{path.toString()}); + EntityDefinition definition = findProperEntityDefinition(path); + + List segments = path.getSegments(); + + List propPathSegments = new ArrayList(); + ItemPath propPath; + for (ItemPathSegment segment : segments) { + QName qname = ItemPath.getName(segment); + if (ObjectType.F_METADATA.equals(qname)) { + continue; + } + // ugly hack: construction/resourceRef -> resourceRef + if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, qname)) { + continue; + } + + // create new property path + propPathSegments.add(new NameItemPathSegment(qname)); + propPath = new ItemPath(propPathSegments); + // get entity query definition + if (QNameUtil.match(qname, ObjectType.F_EXTENSION) || QNameUtil.match(qname, ShadowType.F_ATTRIBUTES)) { + break; + } + + Definition childDef = definition.findDefinition(qname, Definition.class); + if (childDef == null) { + throw new QueryException("Definition '" + definition + "' doesn't contain child definition '" + + qname + "'. Please check your path in query, or query entity/attribute mappings. " + + "Full path was '" + path + "'."); + } + + //todo change this if instanceof and use DefinitionHandler [lazyman] + if (childDef instanceof EntityDefinition) { + EntityDefinition entityDef = (EntityDefinition) childDef; + if (!entityDef.isEmbedded()) { + //create new criteria + LOGGER.trace("Adding criteria '{}' to context based on sub path\n{}", + new Object[]{entityDef.getJpaName(), propPath.toString()}); + addNewCriteriaToContext(propPath, entityDef, entityDef.getJpaName()); + } else { + // we don't create new sub criteria, just add this new item path to aliases + addPathAliasToContext(propPath); + } + definition = entityDef; + } else if (childDef instanceof AnyDefinition) { + LOGGER.trace("Adding criteria '{}' to context based on sub path\n{}", + new Object[]{childDef.getJpaName(), propPath.toString()}); + addNewCriteriaToContext(propPath, childDef, childDef.getJpaName()); + break; + } else if (childDef instanceof CollectionDefinition) { + LOGGER.trace("Adding criteria '{}' to context based on sub path\n{}", + new Object[]{childDef.getJpaName(), propPath.toString()}); + addNewCriteriaToContext(propPath, childDef, childDef.getJpaName()); + Definition def = ((CollectionDefinition) childDef).getDefinition(); + if (def instanceof EntityDefinition) { + definition = (EntityDefinition) def; + } + } else if (childDef instanceof PropertyDefinition || childDef instanceof ReferenceDefinition) { + break; + } else { + //todo throw something here [lazyman] + throw new QueryException("Not implemented yet."); + } + } + } + + /** + * This method scans {@link ItemPath} in {@link ValueFilter} and looks for virtual properties, collections + * or entities in {@link QueryDefinitionRegistry2}. + *

+ * Virtual definitions offer additional query params, which can be used for filtering - this method updates + * criteria based on {@link VirtualQueryParam}. For example assignments and inducements are defined in two + * collections in schema ({@link AbstractRoleType}), + * but in repository ({@link com.evolveum.midpoint.repo.sql.data.common.RAbstractRole}) they are stored in + * single {@link Set}. + *

+ * TODO: implement definition handlers to get rid of these methods with many instanceOf comparisons. + * + * @param path + * @return {@link Criterion} based on {@link VirtualQueryParam} + * @throws QueryException + */ + private Criterion createVirtualCriterion(ItemPath path) throws QueryException { + LOGGER.trace("Scanning path for virtual definitions to create criteria {}", new Object[]{path.toString()}); + + EntityDefinition definition = findProperEntityDefinition(path); + + List criterions = new ArrayList(); + + List segments = path.getSegments(); + List propPathSegments = new ArrayList(); + + ItemPath propPath; + for (ItemPathSegment segment : segments) { + QName qname = ItemPath.getName(segment); + if (ObjectType.F_METADATA.equals(qname)) { + continue; + } + // ugly hack: construction/resourceRef -> resourceRef + if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, qname)) { + continue; + } + // create new property path + propPathSegments.add(new NameItemPathSegment(qname)); + propPath = new ItemPath(propPathSegments); + + if (QNameUtil.match(qname, ObjectType.F_EXTENSION) || QNameUtil.match(qname, ShadowType.F_ATTRIBUTES)) { + break; + } + + // get entity query definition + Definition childDef = definition.findDefinition(qname, Definition.class); + if (childDef == null) { + throw new QueryException("Definition '" + definition + "' doesn't contain child definition '" + + qname + "'. Please check your path in query, or query entity/attribute mappings. " + + "Full path was '" + path + "'."); + } + + //todo change this if instanceof and use DefinitionHandler [lazyman] + if (childDef instanceof EntityDefinition) { + definition = (EntityDefinition) childDef; + } else if (childDef instanceof CollectionDefinition) { + CollectionDefinition collection = (CollectionDefinition) childDef; + if (childDef instanceof VirtualCollectionDefinition) { + VirtualCollectionDefinition virtual = (VirtualCollectionDefinition) childDef; + + criterions.add(updateMainCriterionQueryParam(virtual.getAdditionalParams(), propPath)); + } + + Definition def = collection.getDefinition(); + if (def instanceof EntityDefinition) { + definition = (EntityDefinition) def; + } + } else if (childDef instanceof PropertyDefinition || childDef instanceof ReferenceDefinition + || childDef instanceof AnyDefinition) { + break; + } else { + //todo throw something here [lazyman] + throw new QueryException("Not implemented yet."); + } + } + + return andCriterions(criterions); + } + + private Criterion andCriterions(List criterions) { + switch (criterions.size()) { + case 0: + return null; + case 1: + return criterions.get(0); + default: + return Restrictions.and(criterions.toArray(new Criterion[criterions.size()])); + } + } + + private Criterion updateMainCriterionQueryParam(VirtualQueryParam[] params, ItemPath propPath) + throws QueryException { + List criterions = new ArrayList(); + + String alias = getContext().getAlias(propPath); + for (VirtualQueryParam param : params) { + Criterion criterion = Restrictions.eq(alias + "." + param.name(), createQueryParamValue(param, propPath)); + criterions.add(criterion); + } + + return andCriterions(criterions); + } + + /** + * This method provides transformation from {@link String} value defined in + * {@link VirtualQueryParam#value()} to real object. Currently only + * to simple types and enum values. + * + * @param param + * @param propPath + * @return real value + * @throws QueryException + */ + private Object createQueryParamValue(VirtualQueryParam param, ItemPath propPath) throws QueryException { + Class type = param.type(); + String value = param.value(); + + try { + if (type.isPrimitive()) { + return type.getMethod("valueOf", new Class[]{String.class}).invoke(null, new Object[]{value}); + } + + if (type.isEnum()) { + return Enum.valueOf(type, value); + } + } catch (Exception ex) { + throw new QueryException("Couldn't transform virtual query parameter '" + + param.name() + "' from String to '" + type + "', reason: " + ex.getMessage(), ex); + } + + throw new QueryException("Couldn't transform virtual query parameter '" + + param.name() + "' from String to '" + type + "', it's not yet implemented."); + } + + private void addPathAliasToContext(ItemPath path) { + ItemPath lastPropPath = path.allExceptLast(); + if (ItemPath.EMPTY_PATH.equivalent(lastPropPath)) { + lastPropPath = null; + } + + String alias = getContext().getAlias(lastPropPath); + getContext().addAlias(path, alias); + } + + protected void addNewCriteriaToContext(ItemPath path, Definition def, String realName) { + ItemPath lastPropPath = path.allExceptLast(); + if (ItemPath.EMPTY_PATH.equivalent(lastPropPath)) { + lastPropPath = null; + } + + // Virtual path is defined for example for virtual collections. {c:role/c:assignment} and {c:role/c:iducement} + // must use the same criteria, therefore {c:role/assigmnents} is also path under which is this criteria saved. + final ItemPath virtualPath = lastPropPath != null ? new ItemPath(lastPropPath, new QName("", realName)) : + new ItemPath(new QName("", realName)); + + Criteria existing = getContext().getCriteria(path); + if (existing != null) { + return; + } + + // If there is already criteria on virtual path, only add new path to aliases and criterias. + Criteria virtualCriteria = getContext().getCriteria(virtualPath); + if (virtualCriteria != null) { + getContext().addAlias(path, virtualCriteria.getAlias()); + getContext().addCriteria(path, virtualCriteria); + return; + } + + // get parent criteria + Criteria pCriteria = getContext().getCriteria(lastPropPath); + + // create new criteria and alias for this relationship + String alias = getContext().addAlias(path, def); + Criteria criteria = pCriteria.createCriteria(realName, alias, JoinType.LEFT_OUTER_JOIN); + getContext().addCriteria(path, criteria); + //also add virtual path to criteria map + getContext().addCriteria(virtualPath, criteria); + } + + protected Criterion createCriterion(String propertyName, Object value, ValueFilter filter) throws QueryException { + ItemRestrictionOperation operation; + if (filter instanceof EqualFilter) { + operation = ItemRestrictionOperation.EQ; + } else if (filter instanceof GreaterFilter) { + GreaterFilter gf = (GreaterFilter) filter; + operation = gf.isEquals() ? ItemRestrictionOperation.GE : ItemRestrictionOperation.GT; + } else if (filter instanceof LessFilter) { + LessFilter lf = (LessFilter) filter; + operation = lf.isEquals() ? ItemRestrictionOperation.LE : ItemRestrictionOperation.LT; + } else if (filter instanceof SubstringFilter) { + SubstringFilter substring = (SubstringFilter) filter; + if (substring.isAnchorEnd()) { + operation = ItemRestrictionOperation.ENDS_WITH; + } else if (substring.isAnchorStart()) { + operation = ItemRestrictionOperation.STARTS_WITH; + } else { + operation = ItemRestrictionOperation.SUBSTRING; + } + } else { + throw new QueryException("Can't translate filter '" + filter + "' to operation."); + } + + QueryContext2 context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + Matcher matcher = interpreter.findMatcher(value); + + String matchingRule = null; + if (filter.getMatchingRule() != null){ + matchingRule = filter.getMatchingRule().getLocalPart(); + } + + return matcher.match(operation, propertyName, value, matchingRule); + } + + protected List createDefinitionPath(ItemPath path) throws QueryException { + List definitions = new ArrayList(); + if (path == null) { + return definitions; + } + + EntityDefinition lastDefinition = findProperEntityDefinition(path); + for (ItemPathSegment segment : path.getSegments()) { + if (lastDefinition == null) { + break; + } + + if (!(segment instanceof NameItemPathSegment)) { + continue; + } + + NameItemPathSegment named = (NameItemPathSegment) segment; + Definition def = lastDefinition.findDefinition(named.getName(), Definition.class); + definitions.add(def); + + if (def instanceof EntityDefinition) { + lastDefinition = (EntityDefinition) def; + } else if (def instanceof CollectionDefinition) { // todo this seems logical but is it correct? [mederly] + def = ((CollectionDefinition) def).getDefinition(); + if (def instanceof EntityDefinition) { + lastDefinition = ((EntityDefinition) def); + } else { + lastDefinition = null; + } + } + } + + return definitions; + } + + protected Object getValue(List values) { + if (values == null || values.isEmpty()) { + return null; + } + + PrismValue val = values.get(0); + if (val instanceof PrismPropertyValue) { + PrismPropertyValue propertyValue = (PrismPropertyValue) val; + return propertyValue.getValue(); + } + + return null; + } + + protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) throws QueryException { + Object value; + if (filter instanceof PropertyValueFilter) { + value = getValue(((PropertyValueFilter) filter).getValues()); + } else { + throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); + } + + //todo remove after some time [lazyman] + //attempt to fix value type for polystring (if it was string in filter we create polystring from it) + if (PolyString.class.equals(def.getJaxbType()) && (value instanceof String)) { + LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", new Object[]{filter}); + value = new PolyString((String) value, (String) value); + } + //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) + if (PolyString.class.equals(def.getJaxbType()) && (value instanceof PolyStringType)) { + LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", new Object[]{filter}); + PolyStringType type = (PolyStringType) value; + value = new PolyString(type.getOrig(), type.getNorm()); + } + + if (String.class.equals(def.getJaxbType()) && (value instanceof QName)) { + //eg. shadow/objectClass + value = RUtil.qnameToString((QName) value); + } + + if (value != null && !def.getJaxbType().isAssignableFrom(value.getClass())) { + throw new QueryException("Value should by type of '" + def.getJaxbType() + "' but it's '" + + value.getClass() + "', filter '" + filter + "'."); + } + + if (def.isEnumerated()) { + value = getRepoEnumValue((Enum) value, def.getJpaType()); + } + + return value; + } + + private Enum getRepoEnumValue(Enum schemaValue, Class repoType) throws QueryException { + if (schemaValue == null) { + return null; + } + + if (SchemaEnum.class.isAssignableFrom(repoType)) { + return (Enum) RUtil.getRepoEnumValue(schemaValue, repoType); + } + + Object[] constants = repoType.getEnumConstants(); + for (Object constant : constants) { + Enum e = (Enum) constant; + if (e.name().equals(schemaValue.name())) { + return e; + } + } + + throw new QueryException("Unknown enum value '" + schemaValue + "', which is type of '" + + schemaValue.getClass() + "'."); + } + + protected String createPropertyOrReferenceNamePrefix(ItemPath path) throws QueryException { + StringBuilder sb = new StringBuilder(); + + EntityDefinition definition = findProperEntityDefinition(path); + + List segments = path.getSegments(); + for (ItemPathSegment segment : segments) { + QName qname = ItemPath.getName(segment); + if (ObjectType.F_METADATA.equals(qname)) { // todo not QNameUtil.match? [mederly] + continue; + } + if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, qname)) { // ugly hack: construction/resourceRef -> resourceRef + continue; + } + + // get entity query definition + Definition childDef = definition.findDefinition(qname, Definition.class); + + //todo change this if instanceof and use DefinitionHandler [lazyman] + if (childDef instanceof EntityDefinition) { + EntityDefinition entityDef = (EntityDefinition) childDef; + if (entityDef.isEmbedded()) { + // we don't create new sub criteria, just add dot with jpaName + sb.append(entityDef.getJpaName()); + sb.append('.'); + } + definition = entityDef; + } else if (childDef instanceof CollectionDefinition) { + Definition def = ((CollectionDefinition) childDef).getDefinition(); + if (def instanceof EntityDefinition) { + definition = (EntityDefinition) def; + } + } else if (childDef instanceof PropertyDefinition || childDef instanceof ReferenceDefinition) { + break; + } else { + throw new QueryException("Not implemented yet. Create property name prefix for segment '" + + segment + "', path '" + path + "'."); + } + } + + return sb.toString(); + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java new file mode 100644 index 00000000000..818a3a18f0a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +/** + * @author lazyman + */ +public enum ItemRestrictionOperation { + + EQ, GT, GE, LT, LE, NULL, NOT_NULL, SUBSTRING, STARTS_WITH, ENDS_WITH; +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java new file mode 100644 index 00000000000..a1da90c6284 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.LogicalFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import org.hibernate.criterion.Criterion; + +/** + * @author lazyman + */ +public abstract class LogicalRestriction extends Restriction { + + @Override + public boolean canHandle(ObjectFilter filter) { + if (filter instanceof LogicalFilter) { + return true; + } + + return false; + } + + protected Criterion interpretChildFilter(ObjectFilter filter) throws QueryException { + QueryContext2 context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + return interpreter.interpretFilter(filter, context, this); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java new file mode 100644 index 00000000000..a2bda3ead7f --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.NaryLogicalFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Junction; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author lazyman + */ +public abstract class NaryLogicalRestriction extends LogicalRestriction { + + private static final Trace LOGGER = TraceManager.getTrace(NaryLogicalRestriction.class); + private List restrictions; + + @Override + public boolean canHandle(ObjectFilter filter) { + if (filter instanceof NaryLogicalFilter) { + return true; + } + + return false; + } + + public List getRestrictions() { + if (restrictions == null) { + restrictions = new ArrayList<>(); + } + return restrictions; + } + + protected void validateFilter(NaryLogicalFilter filter) throws QueryException { + if (filter.getConditions() == null || filter.getConditions().isEmpty()) { + LOGGER.trace("NaryLogicalFilter filter must have at least two conditions in it. " + + "Removing logical filter and processing simple condition."); + throw new QueryException("NaryLogicalFilter filter '" + filter.debugDump() + + "' must have at least two conditions in it. Removing logical filter and processing simple condition."); + } + } + + protected Junction updateJunction(List conditions, Junction junction) + throws QueryException { + + QueryContext2 context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + + for (ObjectFilter condition : conditions) { + Criterion criterion = interpreter.interpretFilter(condition, context, this); + junction.add(criterion); + } + + return junction; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java new file mode 100644 index 00000000000..f73ff2c3dfc --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.NotFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +/** + * @author lazyman + */ +public class NotRestriction extends UnaryLogicalRestriction { + + @Override + public boolean canHandle(ObjectFilter filter) { + if (!super.canHandle(filter)) { + return false; + } + + return (filter instanceof NotFilter); + } + + + @Override + public Criterion interpret() throws QueryException { + validateFilter(filter); + Criterion criterion = interpretChildFilter(filter.getFilter()); + + return Restrictions.not(criterion); + } + + @Override + public NotRestriction newInstance() { + return new NotRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java new file mode 100644 index 00000000000..ed6ad808e6b --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Disjunction; +import org.hibernate.criterion.Restrictions; + +/** + * @author lazyman + */ +public class OrRestriction extends NaryLogicalRestriction { + + @Override + public boolean canHandle(ObjectFilter filter) { + if (!super.canHandle(filter)) { + return false; + } + + return (filter instanceof OrFilter); + } + + @Override + public Criterion interpret() + throws QueryException { + + validateFilter(filter); + + Disjunction disjunction = Restrictions.disjunction(); + updateJunction(filter.getConditions(), disjunction); + + return disjunction; + } + + @Override + public OrRestriction newInstance() { + return new OrRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java new file mode 100644 index 00000000000..c50aa0f7c4c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.OrgFilter; +import com.evolveum.midpoint.repo.sql.data.common.RObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.ROrgClosure; +import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Property; +import org.hibernate.criterion.Restrictions; +import org.hibernate.criterion.Subqueries; +import org.hibernate.type.StringType; +import org.hibernate.type.Type; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class OrgRestriction extends Restriction { + + private static final String QUERY_PATH = "descendants"; + private static final ItemPath QUERY_ITEM_PATH = new ItemPath(new QName(RUtil.NS_SQL_REPO, QUERY_PATH)); + + private static final String CLOSURE_ALIAS = "closure"; + private static final String DEPTH = CLOSURE_ALIAS + ".depth"; + + @Override + public boolean canHandle(ObjectFilter filter) { + if (filter instanceof OrgFilter) { + return true; + } + return false; + } + + @Override + public Criterion interpret() throws QueryException { + if (filter.isRoot()) { +// Criteria pCriteria = getInterpreter().getCriteria(null); + DetachedCriteria dc = DetachedCriteria.forClass(ROrgClosure.class); + String[] strings = new String[1]; + strings[0] = "descendant.oid"; + Type[] type = new Type[1]; + type[0] = StringType.INSTANCE; + dc.setProjection(Projections.sqlGroupProjection("descendant_oid", "descendant_oid having count(descendant_oid)=1", strings, type)); +// pCriteria.add(Subqueries.in("this.oid", dc)); + return Subqueries.propertyIn("oid", dc); +// Query rootOrgQuery = session.createQuery("select org from ROrg as org where org.oid in (select descendant.oid from ROrgClosure group by descendant.oid having count(descendant.oid)=1)"); + } + + if (filter.getOrgRef() == null) { + throw new QueryException("No organization reference defined in the search query."); + } + + if (filter.getOrgRef().getOid() == null) { + throw new QueryException("No oid specified in organization reference " + filter.getOrgRef().debugDump()); + } + + DetachedCriteria detached; + switch (filter.getScope()) { + case ONE_LEVEL: + detached = DetachedCriteria.forClass(RObjectReference.class, "p"); + detached.add(Restrictions.eq("referenceType", RReferenceOwner.OBJECT_PARENT_ORG)); + detached.setProjection(Projections.distinct(Projections.property("p.ownerOid"))); + detached.add(Restrictions.eq("p.targetOid", filter.getOrgRef().getOid())); + break; + case SUBTREE: + default: + detached = DetachedCriteria.forClass(RObjectReference.class, "p"); + detached.add(Restrictions.eq("referenceType", RReferenceOwner.OBJECT_PARENT_ORG)); + detached.setProjection(Projections.distinct(Projections.property("p.ownerOid"))); + detached.add(Property.forName("targetOid").in( + DetachedCriteria.forClass(ROrgClosure.class, "cl") + .setProjection(Projections.property("cl.descendantOid")) + .add(Restrictions.eq("cl.ancestorOid", filter.getOrgRef().getOid())))); + } + String mainAlias = getContext().getAlias(null); + return Subqueries.propertyIn(mainAlias + ".oid", detached); + } + + @Override + public OrgRestriction newInstance() { + return new OrgRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java new file mode 100644 index 00000000000..e9ff2df30e1 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.StringUtils; +import org.hibernate.criterion.Criterion; + +/** + * @author lazyman + */ +public class PropertyRestriction extends ItemRestriction { + + private static final Trace LOGGER = TraceManager.getTrace(PropertyRestriction.class); + + @Override + public boolean canHandle(ObjectFilter filter) throws QueryException { + if (!super.canHandle(filter)) { + return false; + } + + ValueFilter valFilter = (ValueFilter) filter; + ItemPath fullPath = valFilter.getFullPath(); + + PropertyDefinition def = findProperDefinition(fullPath, PropertyDefinition.class); + return def != null; + } + + @Override + public Criterion interpretInternal(ValueFilter filter) + throws QueryException { + QueryContext2 context = getContext(); + + ItemPath fullPath = filter.getFullPath(); + PropertyDefinition def = findProperDefinition(fullPath, PropertyDefinition.class); + if (def.isLob()) { + throw new QueryException("Can't query based on clob property value '" + def + "'."); + } + + String propertyName = def.getJpaName(); + String alias = context.getAlias(filter.getParentPath()); + + StringBuilder sb = new StringBuilder(); + if (StringUtils.isNotEmpty(alias)) { + sb.append(alias); + sb.append('.'); + } + sb.append(createPropertyOrReferenceNamePrefix(fullPath)); + sb.append(propertyName); + + Object value = getValueFromFilter(filter, def); + + String propertyPath = sb.toString(); + Criterion criterion = createCriterion(propertyPath, value, filter); + return addIsNotNullIfNecessary(criterion, propertyPath); + } + + @Override + public PropertyRestriction newInstance() { + return new PropertyRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java new file mode 100644 index 00000000000..e516edaffd1 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.PrismConstants; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.RefFilter; +import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; +import org.apache.commons.lang.StringUtils; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +import javax.xml.namespace.QName; +import java.util.List; + +/** + * @author lazyman + */ +public class ReferenceRestriction extends ItemRestriction { + + @Override + public boolean canHandle(ObjectFilter filter) { + if (filter instanceof RefFilter) { + return true; + } + return false; + } + + // modelled after PropertyRestriction.interpretInternal, with some differences + @Override + public Criterion interpretInternal(RefFilter filter) throws QueryException { + + // let's check the value (null is not supported yet) + List values = filter.getValues(); + if (values != null && values.size() > 1) { + throw new QueryException("Ref filter '" + filter + "' contain more than one reference value (which is not supported for now)."); + } + PrismReferenceValue refValue = null; + if (values != null && !values.isEmpty()) { + refValue = (PrismReferenceValue) values.get(0); + } + + QueryContext2 context = getContext(); + + ItemPath fullPath = filter.getFullPath(); + // actually, we cannot look for ReferenceDefinition here, because e.g. linkRef has a CollectionDefinition + Definition def = findProperDefinition(fullPath, Definition.class); + if (def == null) { + throw new QueryException("Definition for " + fullPath + " couldn't be found."); + } + + // ugly hacking, todo refactor! + StringBuilder sb = new StringBuilder(); + if (def instanceof ReferenceDefinition) { + ItemPath parentPath = filter.getParentPath(); + // hack: construction/resourceRef->resourceRef + if (QNameUtil.match(ConstructionType.F_RESOURCE_REF, filter.getElementName()) && + parentPath != null && parentPath.last() instanceof NameItemPathSegment && + QNameUtil.match(AssignmentType.F_CONSTRUCTION, ((NameItemPathSegment) parentPath.last()).getName())) { + parentPath = parentPath.allExceptLast(); + } + String alias = context.getAlias(parentPath); + if (StringUtils.isNotEmpty(alias)) { + sb.append(alias); + sb.append('.'); + } + sb.append(createPropertyOrReferenceNamePrefix(filter.getPath())); // i'm not sure about this [mederly] + String referenceName = def.getJpaName(); + sb.append(referenceName); + sb.append("."); + } else { + String alias = context.getAlias(filter.getPath()); + if (StringUtils.isNotEmpty(alias)) { + sb.append(alias); + sb.append('.'); + } + sb.append(createPropertyOrReferenceNamePrefix(filter.getPath())); // i'm not sure about this [mederly] + } + String prefix = sb.toString(); + + String refValueOid = null; + QName refValueRelation = null; + QName refValueTargetType = null; + if (refValue != null) { + refValueOid = refValue.getOid(); + refValueRelation = refValue.getRelation(); + refValueTargetType = refValue.getTargetType(); + } + Conjunction conjunction = Restrictions.conjunction(); + conjunction.add(handleEqOrNull(prefix + ObjectReference.F_TARGET_OID, refValueOid)); + + if (refValueOid != null) { + if (refValueRelation == null) { + // Return only references without relation + conjunction.add(Restrictions.eq(prefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); + } else if (refValueRelation.equals(PrismConstants.Q_ANY)) { + // Return all relations => no restriction + } else { + // return references with specific relation + conjunction.add(handleEqOrNull(prefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); + } + + if (refValueTargetType != null) { + conjunction.add(handleEqOrNull(prefix + ObjectReference.F_TYPE, + ClassMapper.getHQLTypeForQName(refValueTargetType))); + } + } + + // TODO what about isNotNull if necessary ? + + return conjunction; + } + + @Override + public ReferenceRestriction newInstance() { + return new ReferenceRestriction(); + } + + private Criterion handleEqOrNull(String propertyName, Object value) { + if (value == null) { + return Restrictions.isNull(propertyName); + } + + return Restrictions.eq(propertyName, value); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java new file mode 100644 index 00000000000..7fd9b471bd8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.NotFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.NotNullExpression; +import org.hibernate.criterion.NullExpression; +import org.hibernate.criterion.Restrictions; + +/** + * @author lazyman + */ +public abstract class Restriction { + + protected QueryContext2 context; + protected Restriction parent; + protected T filter; + + public T getFilter() { + return filter; + } + + public void setFilter(T filter) { + this.filter = filter; + } + + public QueryContext2 getContext() { + return context; + } + + public void setContext(QueryContext2 context) { + this.context = context; + } + + public Restriction getParent() { + return parent; + } + + public void setParent(Restriction parent) { + this.parent = parent; + } + + public abstract Criterion interpret() throws QueryException; + + public abstract boolean canHandle(ObjectFilter filter) throws QueryException; + + // todo don't know if cloning is necessary... [lazyman] + // this can be replaced probably by simple java reflection call + public abstract Restriction newInstance(); + + protected boolean isNegated() { + return filter instanceof NotFilter || (parent != null && parent.isNegated()); + } + + /** + * Filter of type NOT(PROPERTY=VALUE) causes problems when there are entities with PROPERTY set to NULL. + * + * Such a filter has to be treated like + * + * NOT (PROPERTY=VALUE & PROPERTY IS NOT NULL) + * + * TODO implement for restrictions other than PropertyRestriction. + */ + protected Criterion addIsNotNullIfNecessary(Criterion criterion, String propertyPath) { + if (criterion instanceof NullExpression || criterion instanceof NotNullExpression) { + return criterion; + } + if (!isNegated()) { + return criterion; + } + Conjunction conjunction = Restrictions.conjunction(); + conjunction.add(criterion); + conjunction.add(Restrictions.isNotNull(propertyPath)); + return conjunction; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java new file mode 100644 index 00000000000..01fdc0133df --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +import javax.xml.namespace.QName; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * @author lazyman + */ +public class TypeRestriction extends Restriction { + + @Override + public Criterion interpret() throws QueryException { + String property = getContext().getAlias(null) + "." + RObject.F_OBJECT_TYPE_CLASS; + + Set values = getValues(filter.getType()); + + Criterion basedOnType; + if (values.size() > 1) { + basedOnType = Restrictions.in(property, values); + } else { + basedOnType = Restrictions.eq(property, values.iterator().next()); + } + + if (filter.getFilter() == null) { + return basedOnType; + } + + QueryContext2 context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + Criterion basedOnFilter = interpreter.interpretFilter(filter.getFilter(), context, this); + + return Restrictions.and(basedOnType, basedOnFilter); + } + + private Set getValues(QName typeQName) { + Set set = new HashSet<>(); + + RObjectType type = ClassMapper.getHQLTypeForQName(typeQName); + set.add(type); + + switch (type) { + case OBJECT: + set.addAll(Arrays.asList(RObjectType.values())); + break; + case FOCUS: + set.add(RObjectType.USER); + case ABSTRACT_ROLE: + set.add(RObjectType.ROLE); + set.add(RObjectType.ORG); + break; + default: + } + + return set; + } + + @Override + public boolean canHandle(ObjectFilter filter) throws QueryException { + if (filter instanceof TypeFilter) { + return true; + } + return false; + } + + @Override + public Restriction newInstance() { + return new TypeRestriction(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java new file mode 100644 index 00000000000..8ac321ff9aa --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.UnaryLogicalFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; + +/** + * @author lazyman + */ +public abstract class UnaryLogicalRestriction extends LogicalRestriction { + + private static final Trace LOGGER = TraceManager.getTrace(UnaryLogicalRestriction.class); + + @Override + public boolean canHandle(ObjectFilter filter) { + if (filter instanceof UnaryLogicalFilter) { + return true; + } + + return false; + } + + protected void validateFilter(UnaryLogicalFilter filter) throws QueryException { + if (filter.getFilter() == null) { + LOGGER.trace("UnaryLogicalFilter filter must have child filter defined in it."); + throw new QueryException("UnaryLogicalFilter '" + filter.debugDump() + + "' must have child filter defined in it."); + } + } +} From 0583b70e5d1599b3e9f2feb40a17010aac32c888 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 20 Nov 2015 23:54:41 +0100 Subject: [PATCH 010/116] "Advanced" query interpreter half baked. Interim commit, not even compilable. --- .../midpoint/prism/path/ItemPath.java | 6 + .../sql/query2/InterpretationContext.java | 196 ++++++ .../repo/sql/query2/QueryContext2.java | 166 ----- .../repo/sql/query2/QueryEngine2.java | 10 +- .../repo/sql/query2/QueryInterpreter2.java | 333 +++++----- .../repo/sql/query2/RQueryCriteriaImpl.java | 58 -- .../definition/CollectionDefinition.java | 7 + .../sql/query2/definition/Definition.java | 42 +- .../query2/definition/EntityDefinition.java | 108 ++-- .../query2/definition/JpaDefinitionPath.java | 58 ++ .../sql/query2/definition/JpaNamePath.java | 53 ++ .../query2/definition/PathTranslation.java | 45 ++ .../repo/sql/query2/hqm/EntityReference.java | 98 +++ .../repo/sql/query2/hqm/HibernateQuery.java | 189 ++++++ .../sql/query2/hqm/JoinSpecification.java | 75 +++ .../sql/query2/hqm/ProjectionElement.java | 48 ++ .../query2/hqm/condition/AndCondition.java | 26 + .../sql/query2/hqm/condition/Condition.java | 98 +++ .../query2/hqm/condition/EqualsCondition.java | 34 ++ .../sql/query2/hqm/condition/InCondition.java | 41 ++ .../hqm/condition/IsNotNullCondition.java | 27 + .../query2/hqm/condition/IsNullCondition.java | 26 + .../hqm/condition/JunctionCondition.java | 39 ++ .../query2/hqm/condition/NotCondition.java | 29 + .../sql/query2/hqm/condition/OrCondition.java | 23 + .../hqm/condition/PropertyCondition.java | 36 ++ .../sql/query2/matcher/DefaultMatcher.java | 4 +- .../repo/sql/query2/matcher/Matcher.java | 35 +- .../sql/query2/matcher/PolyStringMatcher.java | 14 +- .../sql/query2/matcher/StringMatcher.java | 4 +- .../query2/restriction/AndRestriction.java | 28 +- .../restriction/AnyPropertyRestriction.java | 87 +-- .../restriction/CollectionRestriction.java | 48 +- .../query2/restriction/InOidRestriction.java | 25 +- .../query2/restriction/ItemRestriction.java | 571 +++++------------- .../restriction/LogicalRestriction.java | 19 - .../restriction/NaryLogicalRestriction.java | 33 +- .../query2/restriction/NotRestriction.java | 30 +- .../sql/query2/restriction/OrRestriction.java | 31 +- .../query2/restriction/OrgRestriction.java | 81 +-- .../restriction/PropertyRestriction.java | 57 +- .../restriction/ReferenceRestriction.java | 81 +-- .../sql/query2/restriction/Restriction.java | 83 ++- .../query2/restriction/TypeRestriction.java | 35 +- .../restriction/UnaryLogicalRestriction.java | 17 +- 45 files changed, 1838 insertions(+), 1316 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/ProjectionElement.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index cfe603ac817..c17dc9a3967 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -74,6 +74,12 @@ public ItemPath(ItemPath parentPath, QName subName) { add(subName); } + public ItemPath(ItemPath parentPath, ItemPath childPath) { + this.segments = new ArrayList<>(parentPath.segments.size()+childPath.segments.size()); + segments.addAll(parentPath.segments); + segments.addAll(childPath.segments); + } + public ItemPath(List segments) { this.segments = new ArrayList(segments.size()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java new file mode 100644 index 00000000000..cd7c0e6af0d --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.restriction.TypeRestriction; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Criteria; +import org.hibernate.Session; + +import javax.xml.namespace.QName; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author lazyman + */ +public class InterpretationContext { + + private QueryInterpreter2 interpreter; + private PrismContext prismContext; + private Session session; + + private Class type; + + private HibernateQuery hibernateQuery; + + // path from the root filter to the current one (necessary when finding correct Restriction) + private List currentFilterPath = new ArrayList<>(); + + public InterpretationContext(QueryInterpreter2 interpreter, Class type, + PrismContext prismContext, Session session) { + this.interpreter = interpreter; + this.type = type; + this.prismContext = prismContext; + this.session = session; + + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + + EntityDefinition primaryEntityDef = registry.findDefinition(type, null, EntityDefinition.class); + this.hibernateQuery = new HibernateQuery(primaryEntityDef); + } + + public PrismContext getPrismContext() { + return prismContext; + } + + public Session getSession() { + return session; + } + + public QueryInterpreter2 getInterpreter() { + return interpreter; + } + + public Class getType() { + return type; + } + + public HibernateQuery getHibernateQuery() { + return hibernateQuery; + } + + public static class ProperDefinitionSearchResult { + EntityDefinition rootEntityDefinition; + T itemDefinition; + + public ProperDefinitionSearchResult(EntityDefinition rootEntityDefinition, T itemDefinition) { + this.rootEntityDefinition = rootEntityDefinition; + this.itemDefinition = itemDefinition; + } + + public EntityDefinition getRootEntityDefinition() { + return rootEntityDefinition; + } + + public T getItemDefinition() { + return itemDefinition; + } + } + + public ProperDefinitionSearchResult findProperDefinition(ItemPath path, Class clazz) { + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + Class objectClass = getType(); + if (!Modifier.isAbstract(objectClass.getModifiers())) { + EntityDefinition entityDefinition = registry.findDefinition(getType(), null, EntityDefinition.class); + T pathDefinition = entityDefinition.findDefinition(path, clazz); + return new ProperDefinitionSearchResult<>(entityDefinition, pathDefinition); + } + + //we should try to find property in descendant classes + for (Class type : findOtherPossibleParents()) { + EntityDefinition entityDefinition = registry.findDefinition(getType(), null, EntityDefinition.class); + T pathDefinition = entityDefinition.findDefinition(path, clazz); + if (pathDefinition != null) { + return new ProperDefinitionSearchResult<>(entityDefinition, pathDefinition); + } + } + return null; + } + + protected EntityDefinition findProperEntityDefinition(ItemPath path) { + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + if (!ObjectType.class.equals(getType())) { + return registry.findDefinition(getType(), null, EntityDefinition.class); + } + + EntityDefinition entity = null; + // we should try to find property in descendant classes + for (Class type : findOtherPossibleParents()) { + entity = registry.findDefinition(type, null, EntityDefinition.class); + Definition def = entity.findDefinition(path, Definition.class); + if (def != null) { + break; + } + } + LOGGER.trace("Found proper entity definition for path {}, {}", path, entity.toString()); + return entity; + } + + private Set> findOtherPossibleParents() { + TypeRestriction typeRestriction = findTypeRestrictionParent(this); + ObjectTypes typeClass; + if (typeRestriction != null) { + TypeFilter filter = typeRestriction.getFilter(); + typeClass = ObjectTypes.getObjectTypeFromTypeQName(filter.getType()); + } else { + typeClass = ObjectTypes.getObjectType(getType()); + } + + Set> classes = new HashSet<>(); + classes.add(typeClass.getClassDefinition()); + + switch (typeClass) { + case OBJECT: + classes.addAll(ObjectTypes.getAllObjectTypes()); + break; + case FOCUS_TYPE: + classes.add(UserType.class); + case ABSTRACT_ROLE: + classes.add(RoleType.class); + classes.add(OrgType.class); + } + + LOGGER.trace("Found possible parents {} for entity definitions.", Arrays.toString(classes.toArray())); + return classes; + } + + public void pushFilter(ObjectFilter filter) { + currentFilterPath.add(filter); + } + + public void popFilter() { + currentFilterPath.remove(currentFilterPath.size() - 1); + } + + public String getCurrentHqlPropertyPath() { + // TODO + } + + private void getCurrentItemPath() { + + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java deleted file mode 100644 index dc0899d2ab5..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryContext2.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2; - -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.util.ClassMapper; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import org.apache.commons.lang.StringUtils; -import org.hibernate.Criteria; -import org.hibernate.Session; - -import javax.xml.namespace.QName; -import java.util.HashMap; -import java.util.Map; - -/** - * @author lazyman - */ -public class QueryContext2 { - - private QueryInterpreter2 interpreter; - private PrismContext prismContext; - private Session session; - - private ObjectQuery query; - - private Class type; - - private final Map criterias = new HashMap(); - private final Map aliases = new HashMap(); - - public QueryContext2(QueryInterpreter2 interpreter, Class type, ObjectQuery query, - PrismContext prismContext, Session session) { - this.interpreter = interpreter; - this.type = type; - this.query = query; - this.prismContext = prismContext; - this.session = session; - - QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - - String alias = addAlias(null, registry.findDefinition(type, null, EntityDefinition.class)); - addCriteria(null, session.createCriteria(ClassMapper.getHQLTypeClass(type), alias)); - } - - public ObjectQuery getQuery() { - return query; - } - - public void setQuery(ObjectQuery query) { - this.query = query; - } - - public PrismContext getPrismContext() { - return prismContext; - } - - public Session getSession() { - return session; - } - - public QueryInterpreter2 getInterpreter() { - return interpreter; - } - - public Class getType() { - return type; - } - - public Criteria getCriteria(ItemPath path) { - return criterias.get(path); - } - - public void addCriteria(ItemPath path, Criteria criteria) { - criterias.put(path, criteria); - } - - public String getAlias(ItemPath path) { - return aliases.get(path); - } - - public void addAlias(ItemPath path, String alias) { - if (aliases.containsKey(path)) { - if (!StringUtils.equals(alias, aliases.get(path))) { - throw new IllegalArgumentException("Path '" + path + "' (" + alias - + ") is already defined in alias map with alias (" + aliases.get(path) + ")."); - } - - return; - } - - aliases.put(path, alias); - } - - public String addAlias(ItemPath path, Definition def) { - QName qname; - if (path == null) { - //get qname from class type - qname = ObjectTypes.getObjectType(type).getQName(); - } else { - if (!path.isEmpty()) { - //get last qname from path - qname = ItemPath.getName(path.last()); - } else { - throw new IllegalArgumentException("Item path must not be empty."); - } - } - - String alias = createAlias(def, qname); - aliases.put(path, alias); - - return alias; - } - - private String createAlias(Definition def, QName qname) { - String prefix; - if (def != null) { - //we want to skip 'R' prefix for entity definition names - int prefixIndex = (def instanceof EntityDefinition) ? 1 : 0; - prefix = Character.toString(def.getJpaName().charAt(prefixIndex)).toLowerCase(); - } else { - prefix = Character.toString(qname.getLocalPart().charAt(0)).toLowerCase(); - } - - int index = 1; - String alias = prefix; - while (hasAlias(alias)) { - alias = prefix + Integer.toString(index); - index++; - - if (index > 5) { - throw new IllegalStateException("Alias index for definition '" + def - + "' is more than 5? This probably should not happen."); - } - } - - return alias; - } - - private boolean hasAlias(String alias) { - return aliases.containsValue(alias); - } - - public boolean hasAlias(ItemPath path) { - return aliases.get(path) != null; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java index 3ea801c3d59..7fde62d2e23 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java @@ -21,6 +21,8 @@ import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.RQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; @@ -49,13 +51,13 @@ public RQuery interpret(ObjectQuery query, Class type, boolean countingObjects, Session session) throws QueryException { QueryInterpreter2 interpreter = new QueryInterpreter2(repoConfiguration); - Criteria criteria = interpreter.interpret(query, type, options, prismContext, countingObjects, session); + HibernateQuery hibernateQuery = interpreter.interpret(query, type, options, prismContext, countingObjects, session); if (countingObjects) { - criteria.setProjection(Projections.rowCount()); + hibernateQuery.addProjectionElement(new ProjectionElement("count(*)")); } else { - criteria.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); + hibernateQuery.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); } - return new RQueryCriteriaImpl(criteria); + return new RQueryImpl(hibernateQuery.getAsHql()); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 67ac0f66757..cce1277fa74 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -17,93 +17,99 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.AllFilter; +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.InOidFilter; +import com.evolveum.midpoint.prism.query.NoneFilter; +import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.query.OrgFilter; +import com.evolveum.midpoint.prism.query.RefFilter; +import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.query.UndefinedFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinitionPath; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.matcher.DefaultMatcher; import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; import com.evolveum.midpoint.repo.sql.query2.matcher.PolyStringMatcher; import com.evolveum.midpoint.repo.sql.query2.matcher.StringMatcher; +import com.evolveum.midpoint.repo.sql.query2.restriction.AndRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.AnyPropertyRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.CollectionRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.InOidRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.NotRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.OrRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.OrgRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.PropertyRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.ReferenceRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.Restriction; -import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.query2.restriction.TypeRestriction; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.util.ClassPathUtil; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import org.apache.commons.lang.Validate; -import org.apache.commons.lang.reflect.ConstructorUtils; -import org.hibernate.Criteria; import org.hibernate.Session; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Order; -import org.hibernate.criterion.ProjectionList; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; -import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import static com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl.ObjectPagingAfterOid; +import static com.evolveum.midpoint.repo.sql.query2.InterpretationContext.ProperDefinitionSearchResult; /** + * Interprets midPoint queries by translating them to hibernate (HQL) ones. + * + * There are two parts: + * - filter translation, + * - paging translation. + * + * As for filter translation, we traverse the filter depth-first, creating an isomorphic structure of Restrictions. + * While creating them, we continually build a set of entity references that are necessary to evaluate the query; + * these references are in the form of cartesian join of entities from which each one can have a set of entities + * connected to it via left outer join. An example: + * + * from + * RUser u + * left join u.assignments a with ... + * left join u.organization o, + * RRole r + * left join r.assignments a2 with ... + * + * This structure is maintained in InterpretationContext, namely in the HibernateQuery being prepared. (In order to + * produce HQL, we use ad-hoc "hibernate query model" in hqm package, rooted in HibernateQuery class.) + * + * Paging translation is done after filters are translated. It may add some entity references as well, if they are not + * already present. + * * @author lazyman + * @author mederly */ public class QueryInterpreter2 { private static final Trace LOGGER = TraceManager.getTrace(QueryInterpreter2.class); - private static final Set AVAILABLE_RESTRICTIONS; private static final Map AVAILABLE_MATCHERS; - static { - Set restrictions = new HashSet(); - - String packageName = Restriction.class.getPackage().getName(); - Set classes = ClassPathUtil.listClasses(packageName); - LOGGER.debug("Found {} classes in package {}.", new Object[]{classes.size(), packageName}); - for (Class clazz : classes) { - if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { - //we don't need interfaces and abstract classes - continue; - } - - if (!Restriction.class.isAssignableFrom(clazz)) { - //we don't need classes that don't inherit from Restriction - continue; - } - - try { - Restriction restriction = (Restriction) ConstructorUtils.invokeConstructor(clazz, null); - restrictions.add(restriction); - - LOGGER.debug("Added '{}' instance to available restrictions.", - new Object[]{restriction.getClass().getName()}); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "Error occurred during query interpreter initialization", ex); - if (ex instanceof SystemException) { - throw (SystemException) ex; - } - throw new SystemException(ex.getMessage(), ex); - } - } - - AVAILABLE_RESTRICTIONS = Collections.unmodifiableSet(restrictions); - } - static { Map matchers = new HashMap(); //default matcher with null key @@ -111,7 +117,6 @@ public class QueryInterpreter2 { matchers.put(PolyString.class, new PolyStringMatcher()); matchers.put(String.class, new StringMatcher()); - AVAILABLE_MATCHERS = Collections.unmodifiableMap(matchers); } @@ -125,7 +130,7 @@ public SqlRepositoryConfiguration getRepoConfiguration() { return repoConfiguration; } - public Criteria interpret(ObjectQuery query, Class type, + public HibernateQuery interpret(ObjectQuery query, Class type, Collection> options, PrismContext prismContext, boolean countingObjects, Session session) throws QueryException { Validate.notNull(type, "Type must not be null."); @@ -136,57 +141,35 @@ public Criteria interpret(ObjectQuery query, Class type, LOGGER.trace("Interpreting query for type '{}', query:\n{}", new Object[]{type, query}); } - Criteria criteria; - if (query != null && query.getFilter() != null) { - criteria = interpretQuery(query, type, prismContext, session); - } else { - criteria = session.createCriteria(ClassMapper.getHQLTypeClass(type)); - } + InterpretationContext context = new InterpretationContext(this, type, prismContext, session); - if (query != null && query.getPaging() instanceof ObjectPagingAfterOid) { - ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); - if (paging.getOidGreaterThan() != null) { - criteria = criteria.add(Restrictions.gt("oid", paging.getOidGreaterThan())); - } - } + interpretQueryFilter(query, context); + interpretPagingAndSorting(query, context, countingObjects); - if (!countingObjects && query != null && query.getPaging() != null) { - if (query.getPaging() instanceof ObjectPagingAfterOid) { - criteria = updatePagingAndSortingByOid(criteria, query); // very special case - ascending ordering by OID (nothing more) - } else { - criteria = updatePagingAndSorting(criteria, type, query.getPaging()); - } - } + HibernateQuery hibernateQuery = context.getHibernateQuery(); if (!countingObjects) { - ProjectionList projections = Projections.projectionList(); - projections.add(Projections.property("fullObject")); - - projections.add(Projections.property("stringsCount")); - projections.add(Projections.property("longsCount")); - projections.add(Projections.property("datesCount")); - projections.add(Projections.property("referencesCount")); - projections.add(Projections.property("polysCount")); - projections.add(Projections.property("booleansCount")); - - criteria.setProjection(projections); + String rootAlias = hibernateQuery.getPrimaryEntityAlias(); + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".fullObject")); + // TODO other objects if parent is requested? + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".stringsCount")); + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".longsCount")); + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".datesCount")); + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".referencesCount")); + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".polysCount")); + hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".booleansCount")); } - return criteria; + return hibernateQuery; } - private Criteria interpretQuery(ObjectQuery query, Class type, PrismContext prismContext, - Session session) throws QueryException { - ObjectFilter filter = query.getFilter(); + private void interpretQueryFilter(ObjectQuery query, InterpretationContext context) throws QueryException { try { - QueryContext2 context = new QueryContext2(this, type, query, prismContext, session); - - Criterion criterion = interpretFilter(filter, context, null); - - Criteria criteria = context.getCriteria(null); - criteria.add(criterion); - - return criteria; + HibernateQuery hibernateQuery = context.getHibernateQuery(); + if (query != null && query.getFilter() != null) { + Condition c = interpretFilter(query.getFilter(), context, null); + hibernateQuery.addCondition(c); + } } catch (QueryException ex) { throw ex; } catch (Exception ex) { @@ -195,42 +178,137 @@ private Criteria interpretQuery(ObjectQuery query, Class t } } - public Criterion interpretFilter(ObjectFilter filter, QueryContext2 context, Restriction parent) throws QueryException { + public Condition interpretFilter(ObjectFilter filter, InterpretationContext context, Restriction parent) throws QueryException { + context.pushFilter(filter); Restriction restriction = findAndCreateRestriction(filter, context, parent); - Criterion criterion = restriction.interpret(); - return criterion; + Condition condition = restriction.interpret(); + context.popFilter(); + return condition; } - public Criteria updatePagingAndSorting(Criteria query, Class type, ObjectPaging paging) { + private Restriction findAndCreateRestriction(T filter, InterpretationContext context, + Restriction parent) throws QueryException { + + Validate.notNull(filter); + Validate.notNull(context); + + String alias = context.getHibernateQuery().getPrimaryEntityAlias(); + + // the order of processing restrictions can be important, so we do the selection via handwritten code + Restriction restriction; + if (filter instanceof AndFilter) { + restriction = new AndRestriction(); + } else if (filter instanceof OrFilter) { + restriction = new OrRestriction(); + } else if (filter instanceof NotFilter) { + restriction = new NotRestriction(); + } else if (filter instanceof InOidFilter) { + restriction = new InOidRestriction(); + } else if (filter instanceof OrgFilter) { + restriction = new OrgRestriction(); + } else if (filter instanceof TypeFilter) { + restriction = new TypeRestriction(); + } else if (filter instanceof RefFilter) { + ItemPath fullPath = new ItemPath(parent.getItemPathForChildren(), ((RefFilter) filter).getFullPath()); + EntityDefinition entityDefinition = context.findProperEntityDefinition(fullPath); + restriction = new ReferenceRestriction(entityDefinition, alias, entityDefinition); + } else if (filter instanceof ValueFilter) { + ValueFilter valFilter = (ValueFilter) filter; + ItemPath fullPath = new ItemPath(parent.getItemPathForChildren(), valFilter.getFullPath()); + + ProperDefinitionSearchResult propDef = context.findProperDefinition(fullPath, PropertyDefinition.class); + if (propDef != null && propDef.getItemDefinition() != null) { + restriction = new PropertyRestriction(propDef.getRootEntityDefinition(), alias, propDef.getRootEntityDefinition(), propDef.getItemDefinition()); + } else { + ProperDefinitionSearchResult collDef = context.findProperDefinition(fullPath, CollectionDefinition.class); + if (collDef != null && collDef.getItemDefinition() != null && collDef.getItemDefinition().getDefinition() instanceof PropertyDefinition) { + restriction = new CollectionRestriction(collDef.getRootEntityDefinition(), alias, collDef.getItemDefinition()); + } else { + EntityDefinition entityDefinition = context.findProperEntityDefinition(fullPath); + JpaDefinitionPath jpaDefinitionPath = entityDefinition.translatePath(fullPath); + if (fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) || + fullPath.first().equivalent(new NameItemPathSegment(ShadowType.F_ATTRIBUTES)) || + jpaDefinitionPath.containsAnyDefinition()) { + restriction = new AnyPropertyRestriction(entityDefinition, alias, entityDefinition); + } else { + throw new QueryException("Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); + } + } + } + } else if (filter instanceof NoneFilter || filter instanceof AllFilter || filter instanceof UndefinedFilter) { + // these should be filtered out by the client + throw new IllegalStateException("Trivial filters are not supported by QueryInterpreter: " + filter.debugDump()); + } else { + throw new IllegalStateException("Unknown filter: " + filter.debugDump()); + } + + restriction.setContext(context); + restriction.setParent(parent); + restriction.setFilter(filter); + return restriction; + } + + private void interpretPagingAndSorting(ObjectQuery query, InterpretationContext context, boolean countingObjects) { + HibernateQuery hibernateQuery = context.getHibernateQuery(); + String rootAlias = hibernateQuery.getPrimaryEntityAlias(); + + if (query != null && query.getPaging() instanceof ObjectPagingAfterOid) { + ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); + if (paging.getOidGreaterThan() != null) { + hibernateQuery.addCondition(Condition.gt(rootAlias + ".oid", paging.getOidGreaterThan())); + } + } + + if (!countingObjects && query != null && query.getPaging() != null) { + if (query.getPaging() instanceof ObjectPagingAfterOid) { + updatePagingAndSortingByOid(hibernateQuery, (ObjectPagingAfterOid) query.getPaging()); // very special case - ascending ordering by OID (nothing more) + } else { + updatePagingAndSorting(hibernateQuery, context.getType(), query.getPaging()); + } + } + } + + protected void updatePagingAndSortingByOid(HibernateQuery hibernateQuery, ObjectPagingAfterOid paging) { + String rootAlias = hibernateQuery.getPrimaryEntityAlias(); + if (paging.getOrderBy() != null || paging.getDirection() != null || paging.getOffset() != null) { + throw new IllegalArgumentException("orderBy, direction nor offset is allowed on ObjectPagingAfterOid"); + } + hibernateQuery.addOrder(rootAlias + ".oid", OrderDirection.ASCENDING); + if (paging.getMaxSize() != null) { + hibernateQuery.setMaxResults(paging.getMaxSize()); + } + } + + public void updatePagingAndSorting(HibernateQuery hibernateQuery, Class type, ObjectPaging paging) { if (paging == null) { - return query; + return; } if (paging.getOffset() != null) { - query = query.setFirstResult(paging.getOffset()); + hibernateQuery.setFirstResult(paging.getOffset()); } if (paging.getMaxSize() != null) { - query = query.setMaxResults(paging.getMaxSize()); + hibernateQuery.setMaxResults(paging.getMaxSize()); } if (paging.getDirection() == null && (paging.getOrderBy() == null || paging.getOrderBy().isEmpty())) { - return query; + return; } QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); if (paging.getOrderBy() == null || paging.getOrderBy().isEmpty() || paging.getOrderBy().size() > 1 || !(paging.getOrderBy().first() instanceof NameItemPathSegment)) { LOGGER.warn("Ordering by property path with size not equal 1 is not supported '" + paging.getOrderBy() + "'."); - return query; + return; } - EntityDefinition definition = registry.findDefinition(type, null, EntityDefinition.class); - Definition def = definition.findDefinition(paging.getOrderBy(), Definition.class); + // FIXME this has to be enhanced for multi-segment paths! (e.g. create joins if needed) + Definition def = registry.findDefinition(type, paging.getOrderBy(), Definition.class); if (def == null) { LOGGER.warn("Unknown path '" + paging.getOrderBy() + "', couldn't find definition for it, " + "list will not be ordered by it."); - return query; + return; } - String propertyName = def.getJpaName(); + String propertyName = hibernateQuery.getPrimaryEntityAlias() + "." + def.getJpaName(); if (PolyString.class.equals(def.getJaxbType())) { propertyName += ".orig"; } @@ -238,30 +316,15 @@ public Criteria updatePagingAndSorting(Criteria query, Cl if (paging.getDirection() != null) { switch (paging.getDirection()) { case ASCENDING: - query = query.addOrder(Order.asc(propertyName)); + hibernateQuery.addOrder(propertyName, OrderDirection.ASCENDING); break; case DESCENDING: - query = query.addOrder(Order.desc(propertyName)); + hibernateQuery.addOrder(propertyName, OrderDirection.DESCENDING); break; } } else { - query = query.addOrder(Order.asc(propertyName)); - } - - - return query; - } - - protected Criteria updatePagingAndSortingByOid(Criteria criteria, ObjectQuery query) { - ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); - if (paging.getOrderBy() != null || paging.getDirection() != null || paging.getOffset() != null) { - throw new IllegalArgumentException("orderBy, direction nor offset is allowed on ObjectPagingAfterOid"); + hibernateQuery.addOrder(propertyName, OrderDirection.ASCENDING); } - criteria = criteria.addOrder(Order.asc("oid")); - if (paging.getMaxSize() != null) { - criteria = criteria.setMaxResults(paging.getMaxSize()); - } - return criteria; } public Matcher findMatcher(T value) { @@ -274,26 +337,6 @@ public Matcher findMatcher(Class type) { //we return default matcher matcher = AVAILABLE_MATCHERS.get(null); } - return matcher; } - - public Restriction findAndCreateRestriction(T filter, QueryContext2 context, - Restriction parent) throws QueryException { - - for (Restriction restriction : AVAILABLE_RESTRICTIONS) { - Restriction res = restriction.newInstance(); - res.setContext(context); - if (!res.canHandle(filter)) { - continue; - } - res.setParent(parent); - res.setFilter(filter); - - return res; - } - - LOGGER.error("Couldn't find proper restriction that can handle filter '{}'.", new Object[]{filter.debugDump()}); - throw new QueryException("Couldn't find proper restriction that can handle '" + filter + "'"); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java deleted file mode 100644 index 06844423ed5..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/RQueryCriteriaImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2; - -import com.evolveum.midpoint.repo.sql.query.RQuery; -import org.apache.commons.lang.Validate; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.ScrollMode; -import org.hibernate.ScrollableResults; - -import java.util.List; - -/** - * @author lazyman - */ -public class RQueryCriteriaImpl implements RQuery { - - private Criteria criteria; - - public RQueryCriteriaImpl(Criteria criteria) { - Validate.notNull(criteria, "Criteria must not be null."); - this.criteria = criteria; - } - - @Override - public List list() throws HibernateException { - return criteria.list(); - } - - @Override - public Object uniqueResult() throws HibernateException { - return criteria.uniqueResult(); - } - - @Override - public ScrollableResults scroll(ScrollMode mode) throws HibernateException { - return criteria.scroll(mode); - } - - public Criteria getCriteria() { - return criteria; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java index c63edbcb7f3..6a0fdc4e87e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java @@ -16,7 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.Holder; import javax.xml.namespace.QName; @@ -39,6 +41,11 @@ void setDefinition(Definition definition) { this.definition = definition; } + @Override + public Definition nextDefinition(Holder pathHolder) { + return definition; + } + @Override protected void toStringExtended(StringBuilder builder) { String def = definition != null ? definition.toString() : null; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java index 873aec73e64..dcf56e8a9e3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java @@ -17,7 +17,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.restriction.PathTranslation; import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.Holder; import javax.xml.namespace.QName; @@ -111,10 +113,48 @@ public String debugDump(int indent) { */ protected abstract String getDebugDumpClassName(); - public D findDefinition(ItemPath path, Class type) { + /** + * Tries to find "next step" in the definition chain for a given ItemPath. + * Parts of the path that have no representation in the repository (e.g. metadata, + * construction) are simply skipped. + * + * On return, ItemPath (pathHolder) contains the remainder that is to be resolved. + * + * @param pathHolder + * @param + * @return + */ + public Definition nextDefinition(Holder pathHolder) { + return null; + } + + public JpaDefinitionPath translatePath(ItemPath path) { return null; } + /** + * Resolves the whole ItemPath. + * @return + */ + public D findDefinition(ItemPath path, Class type) { + Holder pathHolder = new Holder<>(path); + Definition currentDefinition = this; + for (;;) { + ItemPath currentPath = pathHolder.getValue(); + if (currentPath == null || currentPath.isEmpty()) { + if (type.isAssignableFrom(currentDefinition.getClass())) { + return (D) currentDefinition; + } else { + return null; + } + } + currentDefinition = currentDefinition.nextDefinition(pathHolder); + if (currentDefinition == null) { + return null; + } + } + } + public D findDefinition(QName jaxbName, Class type) { return null; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java index a9e52d160b8..98d6bbc4075 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java @@ -18,7 +18,9 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.repo.sql.query.restriction.PathTranslation; import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.Holder; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; @@ -55,17 +57,15 @@ void setEmbedded(boolean embedded) { public List getDefinitions() { if (definitions == null) { - definitions = new ArrayList(); + definitions = new ArrayList<>(); } - return Collections.unmodifiableList(definitions); } public void addDefinition(Definition definition) { if (definitions == null) { - definitions = new ArrayList(); + definitions = new ArrayList<>(); } - Definition oldDef = findDefinition(definition.getJaxbName(), Definition.class); if (oldDef != null) { definitions.remove(oldDef); @@ -112,46 +112,6 @@ protected String getDebugDumpClassName() { return "Ent"; } - @Override - public D findDefinition(ItemPath path, Class type) { - if (path == null || path.isEmpty()) { - if (type.isAssignableFrom(EntityDefinition.class)) { - return (D) this; - } - } - - NameItemPathSegment first = (NameItemPathSegment) path.first(); - ItemPath tail = path.tail(); - if (ObjectType.F_METADATA.equals(first.getName())) { - //metadata is not an repository entity - first = (NameItemPathSegment) tail.first(); - tail = tail.tail(); - } else if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, first.getName()) && - tail != null && - tail.first() instanceof NameItemPathSegment && - QNameUtil.match(ConstructionType.F_RESOURCE_REF, ((NameItemPathSegment) (tail.first())).getName())) { - // ugly hack: construction/resourceRef -> resourceRef - first = (NameItemPathSegment) tail.first(); - tail = tail.tail(); - } - - if (tail.isEmpty()) { - return findDefinition(first.getName(), type); - } else { - Definition def = findDefinition(first.getName(), Definition.class); - if (def instanceof CollectionDefinition) { - CollectionDefinition collDef = (CollectionDefinition) def; - def = collDef.getDefinition(); - } - - if (def instanceof EntityDefinition) { - EntityDefinition nextEntity = (EntityDefinition) def; - return nextEntity.findDefinition(tail, type); - } - } - - return null; - } @Override public D findDefinition(QName jaxbName, Class type) { @@ -159,14 +119,9 @@ public D findDefinition(QName jaxbName, Class type) { Validate.notNull(type, "Definition type must not be null."); for (Definition definition : getDefinitions()) { - //TODO: using match instead of strict equals..is this OK for repository??this is the situation, we have "common" namepsace if (!QNameUtil.match(jaxbName, definition.getJaxbName())){ continue; } -// if (!jaxbName.equals(definition.getJaxbName())) { -// continue; -// } - if (type.isAssignableFrom(definition.getClass())) { return (D) definition; } @@ -174,4 +129,59 @@ public D findDefinition(QName jaxbName, Class type) { return null; } + + @Override + public Definition nextDefinition(Holder pathHolder) { + ItemPath path = pathHolder.getValue(); + + for (;;) { + if (path == null || path.isEmpty()) { + return this; // in some cases (metadata, construction) this return value might be suspicious, or altogether wrong -- but we don't care + } + + NameItemPathSegment first = (NameItemPathSegment) path.first(); + QName firstName = first.getName(); + + path = path.tail(); + pathHolder.setValue(path); + + // just a lookahead + QName secondName = null; + if (!path.isEmpty() && path.first() instanceof NameItemPathSegment) { + NameItemPathSegment second = ((NameItemPathSegment) (path.first())); + secondName = second.getName(); + } + + // known discrepancies betweeen prism structure and repo representation + if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { + continue; // metadata is not an repository entity + } + if (QNameUtil.match(firstName, AssignmentType.F_CONSTRUCTION) && + QNameUtil.match(secondName, ConstructionType.F_RESOURCE_REF)) { + continue; // construction/resourceRef -> resourceRef + } + + Definition def = findDefinition(firstName, Definition.class); + return def; + } + } + + // beware, path translation can end e.g. in ANY element (extension, attributes) + // also, beware of parent links and cross-entity links + @Override + public JpaDefinitionPath translatePath(ItemPath path) { + Holder pathHolder = new Holder<>(path); + JpaDefinitionPath jpaPath = new JpaDefinitionPath(); + + Definition currentDefinition = this; + for (;;) { + ItemPath currentPath = pathHolder.getValue(); + if (currentPath == null || currentPath.isEmpty()) { + return jpaPath; + } + jpaPath.add(currentDefinition); + currentDefinition = nextDefinition(pathHolder); + } + } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java new file mode 100644 index 00000000000..157c6afd077 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.repo.sql.query.definition.*; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaNamePath; + +import java.util.ArrayList; +import java.util.List; + +/** + * A path of JPA definitions. Analogous to ItemPath; however, expresses the path in JPA terms, not prism terms. + * + * @author mederly + */ +public class JpaDefinitionPath { + + private List definitions = new ArrayList<>(); + + public void add(Definition definition) { + definitions.add(definition); + } + + public List getDefinitions() { + return definitions; + } + + public int size() { + return definitions.size(); + } + + public Definition get(int i) { + return definitions.get(i); + } + + public boolean containsAnyDefinition() { + for (Definition definition : definitions) { + if (definition instanceof AnyDefinition) { + return true; + } + } + return false; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java new file mode 100644 index 00000000000..6f77b302ab9 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.util.ArrayList; +import java.util.List; + +/** + * A path of JPA names. Analogous to ItemPath; however, expresses the path in JPA terms, not prism terms. + * + * @author mederly + */ +public class JpaNamePath { + + private List names = new ArrayList<>(); + + public JpaNamePath(List names) { + this.names = names; + } + + public void add(String jpaName) { + names.add(jpaName); + } + + public List getNames() { + return names; + } + + @Override + public String toString() { + return "JpaNamePath{" + + "names=" + names + + '}'; + } + + public JpaNamePath allExceptLast() { + return new JpaNamePath(names.subList(0, names.size()-1)); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java new file mode 100644 index 00000000000..c1c9c085ca1 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query.restriction; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinitionPath; + +/** + * @author Pavol + */ +public class PathTranslation { + private JpaDefinitionPath jpaDefinitionPath; + private ItemPath itemPathRemainder; + + public PathTranslation(JpaDefinitionPath jpaDefinitionPath, ItemPath itemPathRemainder) { + this.jpaDefinitionPath = jpaDefinitionPath; + this.itemPathRemainder = itemPathRemainder; + } + + public boolean isComplete() { + return ItemPath.isNullOrEmpty(itemPathRemainder); + } + + public JpaDefinitionPath getJpaDefinitionPath() { + return jpaDefinitionPath; + } + + public ItemPath getItemPathRemainder() { + return itemPathRemainder; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java new file mode 100644 index 00000000000..2a811887e1c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm; + +import org.apache.commons.lang.Validate; + +import java.util.ArrayList; +import java.util.List; + +/** + * Specifies an entity that is to be used in the query (its name and its alias), + * along with any entities joined by associations. + * + * + * + * @author mederly + */ +public class EntityReference { + + private String alias; + private String name; + + /** + * Joined entities, e.g. for RUser u here could be: + * - u.assignments a + * - u.longs l with l.ownerType = EXTENSION and l.name = 'http://example.com/p#intType' + * etc. + */ + private List joins = new ArrayList<>(); + + public EntityReference(String alias, String name) { + Validate.notEmpty(alias); + Validate.notEmpty(name); + + this.alias = alias; + this.name = name; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getJoins() { + return joins; + } + + public void addJoin(JoinSpecification join) { + joins.add(join); + } + + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + sb.append(name).append(" ").append(alias); + if (!joins.isEmpty()) { + sb.append("\n"); + JoinSpecification.dumpToHql(sb, joins, indent + 1); + } + + } + + public boolean containsAlias(String alias) { + if (this.alias.equals(alias)) { + return true; + } + for (JoinSpecification join : joins) { + if (join.getAlias().equals(alias)) { + return true; + } + } + return false; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java new file mode 100644 index 00000000000..9b265c4f994 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm; + +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import org.hibernate.Query; +import org.hibernate.transform.ResultTransformer; + +import java.util.ArrayList; +import java.util.List; + +/** + * Query in HQL that is being created. + * + * @author mederly + */ +public class HibernateQuery { + + private static final String INDENT_STRING = " "; + + // projection elements - i.e. select projectionElement1, projectionElement2, ..., projectionElementN from ... + private List projectionElements = new ArrayList<>(); + + /** + * Primary entity for this query, along with joined entities. + * For example, + * RUser u + * Or, + * RUser u + * left join u.assignments a with ... + */ + private EntityReference primaryEntity; + + /** + * All other entities for this query, again along with joined entities. + * For example, if we want to look for a name of assigned entity, i.e. + * UserType: Equal (assignment/target/name, 'Role1'), primary entity is: + * RUser u + * left join u.assignments a with ... + * and secondary one is: + * RObject o + * (with associated condition of o.oid = a.targetRef.targetOid) + */ + private List otherEntities = new ArrayList<>(); + + /** + * List of conditions in the "where" clause. They are to be interpreted as a conjunction. + */ + private List conditions = new ArrayList<>(); + + public HibernateQuery(EntityDefinition primaryEntityDef) { + EntityReference primaryEntity = createItemSpecification(primaryEntityDef); + setPrimaryEntity(primaryEntity); + } + + public List getProjectionElements() { + return projectionElements; + } + + public void addProjectionElement(ProjectionElement element) { + projectionElements.add(element); + } + + public EntityReference getPrimaryEntity() { + return primaryEntity; + } + + public void setPrimaryEntity(EntityReference primaryEntity) { + this.primaryEntity = primaryEntity; + } + + public List getConditions() { + return conditions; + } + + public void addCondition(Condition condition) { + conditions.add(condition); + } + + public Query getAsHql() { + StringBuilder sb = new StringBuilder(); + + sb.append("select\n"); + ProjectionElement.dumpToHql(sb, projectionElements, 1); // we finish at the end of the last line (not at the new line) + sb.append("\n"); + + sb.append("from\n"); + primaryEntity.dumpToHql(sb, 1); + for (EntityReference otherEntity : otherEntities) { + sb.append(",\n"); + otherEntity.dumpToHql(sb, 1); + } + sb.append("\n"); + + if (!conditions.isEmpty()) { + sb.append("where\n"); + Condition.dumpToHql(sb, conditions, 1); + } + return sb.toString(); + } + + public static void indent(StringBuilder sb, int indent) { + while (indent-- > 0) { + sb.append(INDENT_STRING); + } + } + + public EntityReference createItemSpecification(EntityDefinition entityDef) { + String alias = createAlias(entityDef); + return new EntityReference(alias, entityDef.getJpaName()); + } + + public String createAlias(Definition def) { + return createAlias(def.getJpaName(), def instanceof EntityDefinition); + } + + private static final int LIMIT = 100; + + public String createAlias(String name, boolean isEntity) { + String prefix; + + //we want to skip 'R' prefix for entity definition names + int prefixIndex = isEntity ? 1 : 0; + prefix = Character.toString(name.charAt(prefixIndex)).toLowerCase(); + + int index = 1; + String alias = prefix; + while (hasAlias(alias)) { + alias = prefix + Integer.toString(index); + index++; + + if (index > LIMIT) { + throw new IllegalStateException("Alias index for '" + name + + "' is more than " + LIMIT + "? This probably should not happen."); + } + } + + return alias; + } + + private boolean hasAlias(String alias) { + if (primaryEntity.containsAlias(alias)) { + return true; + } + for (EntityReference other : otherEntities) { + if (other.containsAlias(alias)) { + return true; + } + } + return false; + } + + public String getPrimaryEntityAlias() { + return getPrimaryEntity().getAlias(); + } + + public void addOrder(String propertyPath, OrderDirection direction) { + // TODO + } + + public void setMaxResults(Integer size) { + + } + + public void setFirstResult(Integer offset) { + + } + + public void setResultTransformer(ResultTransformer resultTransformer) { + + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java new file mode 100644 index 00000000000..5a9a4e85f5e --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm; + +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import org.apache.commons.lang.Validate; + +import java.util.List; + +/** + * @author mederly + */ +public class JoinSpecification { + + private String alias; + private String path; + private Condition condition; + + public JoinSpecification(String alias, String path, Condition condition) { + Validate.notNull(alias); + Validate.notNull(path); + + this.alias = alias; + this.path = path; + this.condition = condition; + } + + public String getAlias() { + return alias; + } + + public String getPath() { + return path; + } + + public Condition getCondition() { + return condition; + } + + public static void dumpToHql(StringBuilder sb, List joins, int indent) { + boolean first = true; + for (JoinSpecification join : joins) { + if (first) { + first = false; + } else { + sb.append(",\n"); + } + HibernateQuery.indent(sb, indent); + join.dumpToHql(sb); + } + } + + private void dumpToHql(StringBuilder sb) { + sb.append("left join "); + sb.append(path).append(" ").append(alias); + if (condition != null) { + sb.append(" with "); + condition.dumpToHql(sb, -1); + } + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/ProjectionElement.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/ProjectionElement.java new file mode 100644 index 00000000000..9c6ce999bfc --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/ProjectionElement.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm; + +import java.util.List; + +/** + * @author mederly + */ +public class ProjectionElement { + + private String text; + + public ProjectionElement(String text) { + this.text = text; + } + + public static void dumpToHql(StringBuilder sb, List projectionElements, int indent) { + boolean first = true; + for (ProjectionElement element : projectionElements) { + if (first) { + first = false; + } else { + sb.append(",\n"); + } + HibernateQuery.indent(sb, indent); + element.dumpToHql(sb); + } + } + + private void dumpToHql(StringBuilder sb) { + sb.append(text); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java new file mode 100644 index 00000000000..c77687988eb --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +/** + * @author mederly + */ +public class AndCondition extends JunctionCondition { + public AndCondition(Condition... conditions) { + super(conditions); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java new file mode 100644 index 00000000000..6de053b0b2c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.MatchMode; + +import java.io.Serializable; +import java.util.List; + +/** + * Condition in HQL. + * + * @author mederly + */ +public class Condition { + + public void dumpToHql(StringBuilder sb, int indent) { + if (indent >= 0) { + HibernateQuery.indent(sb, indent); + } + // TODO + } + + public static void dumpToHql(StringBuilder sb, List conditions, int indent) { + boolean first = true; + for (Condition condition : conditions) { + if (first) { + first = false; + } else { + sb.append(" and\n"); + } + condition.dumpToHql(sb, indent); + } + } + + public static Condition gt(String propertyPath, Object value) { + //TODO + } + + public static Condition eq(String propertyPath, String value, Class type) { + return null; + } + + public static Condition and(List conditions) { + return null; + } + public static AndCondition and(Condition... conditions) { + return null; + } + + public static Condition isNull(String propertyName) { + return null; + } + + public static Condition eq(String propertyName, Object value) { + return null; + } + + public static Condition ge(String propertyName, Object value) { + return null; + } + + public static Condition lt(String propertyName, Object value) { + return null; + } + + public static Condition le(String propertyName, Object value) { + return null; + } + + public static Condition isNotNull(String propertyName) { + return null; + } + + public static Condition like(String propertyName, String value, MatchMode matchMode) { + return null; + } + + public void ignoreCase() { + + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java new file mode 100644 index 00000000000..23534d72792 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import org.hibernate.Query; + +import java.util.Collection; + +/** + * @author mederly + */ +public class EqualsCondition extends PropertyCondition { + + private Object value; + + public EqualsCondition(String propertyPath, Object value) { + super(propertyPath); + this.value = value; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java new file mode 100644 index 00000000000..befda72202b --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import org.hibernate.Query; + +import java.util.Collection; +import java.util.List; + +/** + * @author mederly + */ +public class InCondition extends PropertyCondition { + + private Collection values; + private Query innerQuery; + + public InCondition(String propertyPath, Query innerQuery) { + super(propertyPath); + this.innerQuery = innerQuery; + } + + public InCondition(String propertyPath, Collection values) { + super(propertyPath); + this.values = values; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java new file mode 100644 index 00000000000..26a75ea5438 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +/** + * @author mederly + */ +public class IsNotNullCondition extends PropertyCondition { + + public IsNotNullCondition(String propertyPath) { + super(propertyPath); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java new file mode 100644 index 00000000000..365ff7e4608 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +/** + * @author mederly + */ +public class IsNullCondition extends PropertyCondition { + public IsNullCondition(String propertyPath) { + super(propertyPath); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java new file mode 100644 index 00000000000..82ecb517f23 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author mederly + */ +public class JunctionCondition extends Condition { + + protected List components = new ArrayList<>(); + + public JunctionCondition(Condition... conditions) { + for (Condition condition : conditions) { + components.add(condition); + } + } + + public void add(Condition condition) { + components.add(condition); + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java new file mode 100644 index 00000000000..bbf29aa2d8e --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +/** + * @author mederly + */ +public class NotCondition extends Condition { + + protected Condition child; + + public NotCondition(Condition child) { + this.child = child; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java new file mode 100644 index 00000000000..08a8f77b7e1 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +/** + * @author mederly + */ +public class OrCondition extends JunctionCondition { +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java new file mode 100644 index 00000000000..19b26fccd90 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class PropertyCondition extends Condition { + + protected String propertyPath; + + public PropertyCondition(String propertyPath) { + Validate.notNull(propertyPath); + this.propertyPath = propertyPath; + } + + public String getPropertyPath() { + return propertyPath; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java index 7d18750cbbf..d5695bf5c8e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java @@ -17,8 +17,8 @@ package com.evolveum.midpoint.repo.sql.query2.matcher; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; -import org.hibernate.criterion.Criterion; /** * @author lazyman @@ -26,7 +26,7 @@ public class DefaultMatcher extends Matcher { @Override - public Criterion match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) + public Condition match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) throws QueryException { return basicMatch(operation, propertyName, value, false); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java index dac655a0ce4..9310cd97654 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.query2.matcher; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.MatchMode; @@ -39,55 +40,55 @@ public abstract class Matcher { * @return * @throws QueryException */ - public abstract Criterion match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) + public abstract Condition match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) throws QueryException; - protected Criterion basicMatch(ItemRestrictionOperation operation, String propertyName, Object value, + protected Condition basicMatch(ItemRestrictionOperation operation, String propertyName, Object value, boolean ignoreCase) throws QueryException { - Criterion criterion; + Condition condition; switch (operation) { case EQ: if (value == null) { - criterion = Restrictions.isNull(propertyName); + condition = Condition.isNull(propertyName); } else { - criterion = Restrictions.eq(propertyName, value); + condition = Condition.eq(propertyName, value); } break; case GT: - criterion = Restrictions.gt(propertyName, value); + condition = Condition.gt(propertyName, value); break; case GE: - criterion = Restrictions.ge(propertyName, value); + condition = Condition.ge(propertyName, value); break; case LT: - criterion = Restrictions.lt(propertyName, value); + condition = Condition.lt(propertyName, value); break; case LE: - criterion = Restrictions.le(propertyName, value); + condition = Condition.le(propertyName, value); break; case NOT_NULL: - criterion = Restrictions.isNotNull(propertyName); + condition = Condition.isNotNull(propertyName); break; case NULL: - criterion = Restrictions.isNull(propertyName); + condition = Condition.isNull(propertyName); break; case STARTS_WITH: - criterion = Restrictions.like(propertyName, (String) value, MatchMode.START); + condition = Condition.like(propertyName, (String) value, MatchMode.START); break; case ENDS_WITH: - criterion = Restrictions.like(propertyName, (String) value, MatchMode.END); + condition = Condition.like(propertyName, (String) value, MatchMode.END); break; case SUBSTRING: - criterion = Restrictions.like(propertyName, (String) value, MatchMode.ANYWHERE); + condition = Condition.like(propertyName, (String) value, MatchMode.ANYWHERE); break; default: throw new QueryException("Unknown operation '" + operation + "'."); } - if (ignoreCase && (value instanceof String) && (criterion instanceof SimpleExpression)) { - criterion = ((SimpleExpression) criterion).ignoreCase(); + if (ignoreCase && (value instanceof String)) { + condition.ignoreCase(); } - return criterion; + return condition; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java index 2d02728905a..36a8d577fca 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java @@ -22,6 +22,8 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; import org.apache.commons.lang.StringUtils; import org.hibernate.criterion.Conjunction; @@ -43,7 +45,7 @@ public class PolyStringMatcher extends Matcher { public static final String NORM_IGNORE_CASE = "normIgnoreCase"; @Override - public Criterion match(ItemRestrictionOperation operation, String propertyName, PolyString value, String matcher) + public Condition match(ItemRestrictionOperation operation, String propertyName, PolyString value, String matcher) throws QueryException { boolean ignoreCase = STRICT_IGNORE_CASE.equals(matcher) @@ -52,9 +54,9 @@ public Criterion match(ItemRestrictionOperation operation, String propertyName, if (StringUtils.isEmpty(matcher) || STRICT.equals(matcher) || STRICT_IGNORE_CASE.equals(matcher)) { - Conjunction conjunction = Restrictions.conjunction(); - conjunction.add(createOrigMatch(operation, propertyName, value, ignoreCase)); - conjunction.add(createNormMatch(operation, propertyName, value, ignoreCase)); + AndCondition conjunction = Condition.and( + createOrigMatch(operation, propertyName, value, ignoreCase), + createNormMatch(operation, propertyName, value, ignoreCase)); return conjunction; } else if (ORIG.equals(matcher) || ORIG_IGNORE_CASE.equals(matcher)) { @@ -66,14 +68,14 @@ public Criterion match(ItemRestrictionOperation operation, String propertyName, } } - private Criterion createNormMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, + private Condition createNormMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, boolean ignoreCase) throws QueryException { String realValue = value != null ? value.getNorm() : null; return basicMatch(operation, propertyName + '.' + RPolyString.F_NORM, realValue, ignoreCase); } - private Criterion createOrigMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, + private Condition createOrigMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, boolean ignoreCase) throws QueryException { String realValue = value != null ? value.getOrig() : null; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java index c9bb925a1a8..3f9e9a84858 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java @@ -18,8 +18,8 @@ import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; -import org.hibernate.criterion.Criterion; /** * @author lazyman @@ -30,7 +30,7 @@ public class StringMatcher extends Matcher { public static final String IGNORE_CASE = StringIgnoreCaseMatchingRule.NAME.getLocalPart(); @Override - public Criterion match(ItemRestrictionOperation operation, String propertyName, String value, String matcher) + public Condition match(ItemRestrictionOperation operation, String propertyName, String value, String matcher) throws QueryException { boolean ignoreCase = IGNORE_CASE.equalsIgnoreCase(matcher); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java index ad37a9eb539..e4cc0c6a9b1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java @@ -16,38 +16,26 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.AndFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; /** * @author lazyman + * @author mederly */ public class AndRestriction extends NaryLogicalRestriction { @Override - public boolean canHandle(ObjectFilter filter) { - if (!super.canHandle(filter)) { - return false; - } - - return (filter instanceof AndFilter); - } - - @Override - public Criterion interpret() throws QueryException { - validateFilter(filter); - Conjunction conjunction = Restrictions.conjunction(); + public Condition interpret() throws QueryException { + validateFilter(); + AndCondition conjunction = new AndCondition(); updateJunction(filter.getConditions(), conjunction); - return conjunction; } - @Override - public AndRestriction newInstance() { - return new AndRestriction(); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index 96cefb91655..ee2f4c0a05c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -20,7 +20,6 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.data.common.any.RAnyConverter; @@ -29,14 +28,14 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Restrictions; import javax.xml.namespace.QName; @@ -50,84 +49,38 @@ public class AnyPropertyRestriction extends ItemRestriction { private static final Trace LOGGER = TraceManager.getTrace(AnyPropertyRestriction.class); - @Override - public boolean canHandle(ObjectFilter filter) throws QueryException { - if (!super.canHandle(filter)) { - return false; - } - - ValueFilter valFilter = (ValueFilter) filter; - ItemPath fullPath = valFilter.getFullPath(); - - List defPath = createDefinitionPath(fullPath); - return containsAnyDefinition(defPath) - || (fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION))) - || (fullPath.first().equivalent(new NameItemPathSegment(ShadowType.F_ATTRIBUTES))); - } - - private boolean containsAnyDefinition(List definitions) { - for (Definition definition : definitions) { - if (definition instanceof AnyDefinition) { - return true; - } - } - - return false; + public AnyPropertyRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { + super(rootEntityDefinition, startPropertyPath, startEntityDefinition); } @Override - public Criterion interpretInternal(ValueFilter filter) throws QueryException { + public Condition interpretInternal(String hqlPath) throws QueryException { ItemDefinition itemDefinition = filter.getDefinition(); - QName name = itemDefinition.getName(); - QName type = itemDefinition.getTypeName(); + QName itemName = itemDefinition.getName(); + QName itemType = itemDefinition.getTypeName(); - if (name == null || type == null) { + if (itemName == null || itemType == null) { throw new QueryException("Couldn't get name or type for queried item '" + itemDefinition + "'"); } - ItemPath anyItemPath = createAnyItemPath(filter.getParentPath(), filter.getDefinition()); - if (!getContext().hasAlias(anyItemPath)) { - QName anyTypeName = ((NameItemPathSegment) anyItemPath.last()).getName(); - LOGGER.trace("Condition item is from 'any' container, adding new criteria based on any type '{}'", - new Object[]{anyTypeName.getLocalPart()}); - addNewCriteriaToContext(anyItemPath, null, anyTypeName.getLocalPart()); - } - String propertyNamePrefix = getContext().getAlias(anyItemPath) + '.'; - - Conjunction conjunction = Restrictions.conjunction(); - - RObjectExtensionType ownerType = filter.getFullPath().first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) ? + ItemPath fullPath = getFullPath(filter.getFullPath()); // TODO does not work for cross-entities! + RObjectExtensionType ownerType = fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) ? RObjectExtensionType.EXTENSION : RObjectExtensionType.ATTRIBUTES; - conjunction.add(Restrictions.eq(propertyNamePrefix + "ownerType", ownerType)); + String anyAssociationName = null; // longs, strings, ... + try { + anyAssociationName = RAnyConverter.getAnySetType(itemDefinition); + } catch (SchemaException e) { + throw new QueryException(e.getMessage(), e); + } + String alias = addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); - conjunction.add(Restrictions.eq(propertyNamePrefix + RAnyValue.F_NAME, RUtil.qnameToString(name))); + String propertyValuePath = alias + '.' + RAnyValue.F_VALUE; Object testedValue = getValue(((PropertyValueFilter) filter).getValues()); Object value = RAnyConverter.getAggregatedRepoObject(testedValue); - conjunction.add(createCriterion(propertyNamePrefix + RAnyValue.F_VALUE, value, filter)); - - // todo what about "not"? but it would not work in this setting anyway (ownerType=A & name=B & value=C) - //conjunction.add(Restrictions.isNotNull(propertyNamePrefix + RAnyValue.F_VALUE)); - return conjunction; - } - - private ItemPath createAnyItemPath(ItemPath path, ItemDefinition itemDef) throws QueryException { - try { - List segments = new ArrayList(); -// segments.addAll(path.getSegments()); - // get any type name (e.g. clobs, strings, dates,...) based on definition - String anyTypeName = RAnyConverter.getAnySetType(itemDef); - segments.add(new NameItemPathSegment(new QName(RUtil.NS_SQL_REPO, anyTypeName))); + Condition c = createCondition(propertyValuePath, value, filter); - return new ItemPath(segments); - } catch (SchemaException ex) { - throw new QueryException(ex.getMessage(), ex); - } - } - - @Override - public AnyPropertyRestriction newInstance() { - return new AnyPropertyRestriction(); + return addIsNotNullIfNecessary(c, propertyValuePath); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java index 977cde61d76..668d0e25110 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java @@ -18,57 +18,41 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import org.hibernate.criterion.Criterion; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import org.apache.commons.lang.Validate; /** * @author lazyman */ public class CollectionRestriction extends ItemRestriction { - @Override - public boolean canHandle(ObjectFilter filter) throws QueryException { - if (!super.canHandle(filter)) { - return false; - } + private CollectionDefinition collectionDefinition; - ValueFilter valFilter = (ValueFilter) filter; - ItemPath fullPath = valFilter.getFullPath(); - - CollectionDefinition def = findProperDefinition(fullPath, CollectionDefinition.class); - if (def == null) { - return false; - } - - return def.getDefinition() instanceof PropertyDefinition; + public CollectionRestriction(EntityDefinition rootEntityDefinition, String alias, CollectionDefinition collectionDefinition) { + super(rootEntityDefinition, alias, rootEntityDefinition); + Validate.notNull(collectionDefinition); + this.collectionDefinition = collectionDefinition; } - @Override - public Criterion interpretInternal(ValueFilter filter) throws QueryException { - ItemPath fullPath = filter.getFullPath(); - QueryContext2 context = getContext(); - CollectionDefinition def = findProperDefinition(fullPath, CollectionDefinition.class); - - String alias = context.getAlias(fullPath); - Object value = getValueFromFilter(filter, (PropertyDefinition) def.getDefinition()); - // TODO what about not-null ? + @Override + public Condition interpretInternal(String hqlPath) throws QueryException { + Object value = getValueFromFilter(filter, (PropertyDefinition) collectionDefinition.getDefinition()); //custom propertyPath handling for PolyString (it's embedded entity, not a primitive) if (value instanceof PolyString) { - return createCriterion(alias, value, filter); + return createCondition(hqlPath, value, filter); } - return createCriterion(alias + ".elements", value, filter); - } + return createCondition(hqlPath + ".elements", value, filter); - @Override - public Restriction newInstance() { - return new CollectionRestriction(); + // TODO what about not-null ? } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java index 1daba227639..9a65b3617eb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java @@ -16,11 +16,13 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.InOidFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; /** * @author lazyman @@ -28,23 +30,8 @@ public class InOidRestriction extends Restriction { @Override - public Criterion interpret() throws QueryException { - String property = getContext().getAlias(null) + ".oid"; - - return Restrictions.in(property, filter.getOids()); + public Condition interpret() throws QueryException { + return new InCondition(context.getCurrentHqlPropertyPath() + ".oid", filter.getOids()); } - @Override - public boolean canHandle(ObjectFilter filter) throws QueryException { - if (filter instanceof InOidFilter) { - return true; - } - - return false; - } - - @Override - public Restriction newInstance() { - return new InOidRestriction(); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index 79e8c8ce476..7151dc42575 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -19,420 +19,201 @@ import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.ItemPathSegment; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.GreaterFilter; import com.evolveum.midpoint.prism.query.LessFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; -import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; -import com.evolveum.midpoint.repo.sql.query2.QueryDefinitionRegistry2; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinitionPath; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualQueryParam; +import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.lang.Validate; -import org.hibernate.Criteria; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; -import org.hibernate.sql.JoinType; import javax.xml.namespace.QName; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; /** + * Abstract superclass for all value-related filters. There are two major problems solved: + * 1) mapping from ItemPath to HQL property paths + * 2) adding joined entities to the query, along with necessary conditions + * (there are two kinds of joins: left outer join and carthesian join) + * + * After the necessary entity is available, the fine work (creating one or more conditions + * to execute the filtering) is done by subclasses of this path in the interpretInternal(..) method. + * * @author lazyman + * @author mederly */ public abstract class ItemRestriction extends Restriction { private static final Trace LOGGER = TraceManager.getTrace(ItemRestriction.class); - @Override - public boolean canHandle(ObjectFilter filter) throws QueryException { - Validate.notNull(filter, "Object filter must not be null."); - if (!(filter instanceof ValueFilter)) { - return false; - } - return true; - } - - @Override - public Criterion interpret() throws QueryException { - - ItemPath path = filter.getFullPath(); - if (path != null) { - // at first we build criterias with aliases - updateQueryContext(path); - } - - Criterion main = interpretInternal(filter); - Criterion virtual = createVirtualCriterion(path); - if (virtual != null) { - return Restrictions.and(virtual, main); - } - - return main; - } - - public abstract Criterion interpretInternal(T filter) throws QueryException; - - private TypeRestriction findTypeRestrictionParent(Restriction restriction) { - if (restriction == null) { - return null; - } - - if (restriction instanceof TypeRestriction) { - return (TypeRestriction) restriction; - } - - return findTypeRestrictionParent(restriction.getParent()); - } - - private Set> findOtherPossibleParents() { - TypeRestriction typeRestriction = findTypeRestrictionParent(this); - ObjectTypes typeClass; - if (typeRestriction != null) { - TypeFilter filter = typeRestriction.getFilter(); - typeClass = ObjectTypes.getObjectTypeFromTypeQName(filter.getType()); - } else { - typeClass = ObjectTypes.getObjectType(getContext().getType()); - } - - Set> classes = new HashSet<>(); - classes.add(typeClass.getClassDefinition()); + /** + * Definition of the root entity. Root entity corresponds to the ObjectType class that was requested + * by the search operation, or the one that was refined from abstract types (ObjectType, AbstractRoleType, ...) + * in the process of restriction construction. + */ + private EntityDefinition rootEntityDefinition; - switch (typeClass) { - case OBJECT: - classes.addAll(ObjectTypes.getAllObjectTypes()); - break; - case FOCUS_TYPE: - classes.add(UserType.class); - case ABSTRACT_ROLE: - classes.add(RoleType.class); - classes.add(OrgType.class); - } + /** + * Property path that is the base of this restriction. + * + * For simple cases like UserType: name, UserType: activation/administrativeStatus etc. the root + * is the query primary entity alias (e.g. u in "RUser u"). + * + * For "ForValue" filters the startPropertyPath corresponds to the base item pointed to by the filter. + * E.g. in "UserType: ForValue (assignment)" it is "a" (provided that there is + * "RUser u left join u.assignments a with ..." already defined). + * + * (Item restriction expects that its root is already defined in the FROM clause.) + */ + private String startPropertyPath; - LOGGER.trace("Found possible parents {} for entity definitions.", Arrays.toString(classes.toArray())); - return classes; + /** + * Definition of the entity when this restriction starts. It is usually the same as rootEntityDefinition, + * but for ForValue children it is the entity pointed to by ForValue restriction. (I.e. assignment in the above + * example.) + */ + private EntityDefinition startEntityDefinition; + + public ItemRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { + Validate.notNull(rootEntityDefinition); + Validate.notNull(startPropertyPath); + Validate.notNull(startEntityDefinition); + this.rootEntityDefinition = rootEntityDefinition; + this.startPropertyPath = startPropertyPath; + this.startEntityDefinition = startEntityDefinition; } - protected T findProperDefinition(ItemPath path, Class clazz) { - QueryContext2 context = getContext(); - QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - if (!ObjectType.class.equals(context.getType())) { - return registry.findDefinition(context.getType(), path, clazz); - } + @Override + public Condition interpret() throws QueryException { - //we should try to find property in descendant classes - for (Class type : findOtherPossibleParents()) { - Definition def = registry.findDefinition(type, path, clazz); - if (def != null) { - return (T) def; - } + ItemPath path = filter.getFullPath(); + if (ItemPath.isNullOrEmpty(path)) { + throw new QueryException("Null or empty path for ItemRestriction in " + filter.debugDump()); } - return null; - } - - protected EntityDefinition findProperEntityDefinition(ItemPath path) { - QueryContext2 context = getContext(); - QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - if (!ObjectType.class.equals(context.getType())) { - return registry.findDefinition(context.getType(), null, EntityDefinition.class); - } + String hqlPropertyPath = prepareJoins(path); - EntityDefinition entity = null; - // we should try to find property in descendant classes - for (Class type : findOtherPossibleParents()) { - entity = registry.findDefinition(type, null, EntityDefinition.class); - Definition def = entity.findDefinition(path, Definition.class); - if (def != null) { - break; - } - } - LOGGER.trace("Found proper entity definition for path {}, {}", path, entity.toString()); - return entity; + Condition condition = interpretInternal(hqlPropertyPath); + return condition; } - //todo reimplement, use DefinitionHandlers or maybe another great concept - private void updateQueryContext(ItemPath path) throws QueryException { - LOGGER.trace("Updating query context based on path {}", new Object[]{path.toString()}); - EntityDefinition definition = findProperEntityDefinition(path); - - List segments = path.getSegments(); - - List propPathSegments = new ArrayList(); - ItemPath propPath; - for (ItemPathSegment segment : segments) { - QName qname = ItemPath.getName(segment); - if (ObjectType.F_METADATA.equals(qname)) { - continue; - } - // ugly hack: construction/resourceRef -> resourceRef - if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, qname)) { - continue; - } - - // create new property path - propPathSegments.add(new NameItemPathSegment(qname)); - propPath = new ItemPath(propPathSegments); - // get entity query definition - if (QNameUtil.match(qname, ObjectType.F_EXTENSION) || QNameUtil.match(qname, ShadowType.F_ATTRIBUTES)) { - break; - } - - Definition childDef = definition.findDefinition(qname, Definition.class); - if (childDef == null) { - throw new QueryException("Definition '" + definition + "' doesn't contain child definition '" - + qname + "'. Please check your path in query, or query entity/attribute mappings. " - + "Full path was '" + path + "'."); - } - - //todo change this if instanceof and use DefinitionHandler [lazyman] - if (childDef instanceof EntityDefinition) { - EntityDefinition entityDef = (EntityDefinition) childDef; + // returns property path that can be used to access the item values + private String prepareJoins(ItemPath relativePath) throws QueryException { + + ItemPath fullPath = getFullPath(relativePath); + LOGGER.trace("Updating query context based on path {}; full path is {}", relativePath, fullPath); + + /** + * We have to do something like this - examples: + * - activation.administrativeStatus -> (nothing, activation is embedded entity) + * - assignment.targetRef -> "left join u.assignments a with ..." + * - assignment.resourceRef -> "left join u.assignments a with ..." + * - organization -> "left join u.organization o" + * + * Or more complex: + * - assignment.modifyApproverRef -> "left join u.assignments a (...) left join a.modifyApproverRef m (...)" + * - assignment.target.longs -> "left join u.assignments a (...), RObject o left join o.longs (...)" + */ + JpaDefinitionPath jpaDefinitionPath = startEntityDefinition.translatePath(relativePath); + String currentHqlPath = startPropertyPath; + + for (Definition definition : jpaDefinitionPath.getDefinitions()) { + if (definition instanceof EntityDefinition) { + EntityDefinition entityDef = (EntityDefinition) definition; if (!entityDef.isEmbedded()) { - //create new criteria - LOGGER.trace("Adding criteria '{}' to context based on sub path\n{}", - new Object[]{entityDef.getJpaName(), propPath.toString()}); - addNewCriteriaToContext(propPath, entityDef, entityDef.getJpaName()); - } else { - // we don't create new sub criteria, just add this new item path to aliases - addPathAliasToContext(propPath); + LOGGER.trace("Adding join for '{}' to context", entityDef.getJpaName()); + currentHqlPath = addJoin(entityDef, currentHqlPath); } - definition = entityDef; - } else if (childDef instanceof AnyDefinition) { - LOGGER.trace("Adding criteria '{}' to context based on sub path\n{}", - new Object[]{childDef.getJpaName(), propPath.toString()}); - addNewCriteriaToContext(propPath, childDef, childDef.getJpaName()); + } else if (definition instanceof AnyDefinition) { + LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); + currentHqlPath = addJoin(definition, currentHqlPath); break; - } else if (childDef instanceof CollectionDefinition) { - LOGGER.trace("Adding criteria '{}' to context based on sub path\n{}", - new Object[]{childDef.getJpaName(), propPath.toString()}); - addNewCriteriaToContext(propPath, childDef, childDef.getJpaName()); - Definition def = ((CollectionDefinition) childDef).getDefinition(); - if (def instanceof EntityDefinition) { - definition = (EntityDefinition) def; - } - } else if (childDef instanceof PropertyDefinition || childDef instanceof ReferenceDefinition) { + } else if (definition instanceof CollectionDefinition) { + LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); + currentHqlPath = addJoin(definition, currentHqlPath); + } else if (definition instanceof PropertyDefinition || definition instanceof ReferenceDefinition) { break; } else { - //todo throw something here [lazyman] throw new QueryException("Not implemented yet."); } + // TODO entity crossjoin references (when crossing object boundaries) } - } - - /** - * This method scans {@link ItemPath} in {@link ValueFilter} and looks for virtual properties, collections - * or entities in {@link QueryDefinitionRegistry2}. - *

- * Virtual definitions offer additional query params, which can be used for filtering - this method updates - * criteria based on {@link VirtualQueryParam}. For example assignments and inducements are defined in two - * collections in schema ({@link AbstractRoleType}), - * but in repository ({@link com.evolveum.midpoint.repo.sql.data.common.RAbstractRole}) they are stored in - * single {@link Set}. - *

- * TODO: implement definition handlers to get rid of these methods with many instanceOf comparisons. - * - * @param path - * @return {@link Criterion} based on {@link VirtualQueryParam} - * @throws QueryException - */ - private Criterion createVirtualCriterion(ItemPath path) throws QueryException { - LOGGER.trace("Scanning path for virtual definitions to create criteria {}", new Object[]{path.toString()}); - - EntityDefinition definition = findProperEntityDefinition(path); - - List criterions = new ArrayList(); - - List segments = path.getSegments(); - List propPathSegments = new ArrayList(); - - ItemPath propPath; - for (ItemPathSegment segment : segments) { - QName qname = ItemPath.getName(segment); - if (ObjectType.F_METADATA.equals(qname)) { - continue; - } - // ugly hack: construction/resourceRef -> resourceRef - if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, qname)) { - continue; - } - // create new property path - propPathSegments.add(new NameItemPathSegment(qname)); - propPath = new ItemPath(propPathSegments); - if (QNameUtil.match(qname, ObjectType.F_EXTENSION) || QNameUtil.match(qname, ShadowType.F_ATTRIBUTES)) { - break; - } - - // get entity query definition - Definition childDef = definition.findDefinition(qname, Definition.class); - if (childDef == null) { - throw new QueryException("Definition '" + definition + "' doesn't contain child definition '" - + qname + "'. Please check your path in query, or query entity/attribute mappings. " - + "Full path was '" + path + "'."); - } - - //todo change this if instanceof and use DefinitionHandler [lazyman] - if (childDef instanceof EntityDefinition) { - definition = (EntityDefinition) childDef; - } else if (childDef instanceof CollectionDefinition) { - CollectionDefinition collection = (CollectionDefinition) childDef; - if (childDef instanceof VirtualCollectionDefinition) { - VirtualCollectionDefinition virtual = (VirtualCollectionDefinition) childDef; - - criterions.add(updateMainCriterionQueryParam(virtual.getAdditionalParams(), propPath)); - } - - Definition def = collection.getDefinition(); - if (def instanceof EntityDefinition) { - definition = (EntityDefinition) def; - } - } else if (childDef instanceof PropertyDefinition || childDef instanceof ReferenceDefinition - || childDef instanceof AnyDefinition) { - break; - } else { - //todo throw something here [lazyman] - throw new QueryException("Not implemented yet."); - } - } - - return andCriterions(criterions); - } - - private Criterion andCriterions(List criterions) { - switch (criterions.size()) { - case 0: - return null; - case 1: - return criterions.get(0); - default: - return Restrictions.and(criterions.toArray(new Criterion[criterions.size()])); - } + return currentHqlPath; } - private Criterion updateMainCriterionQueryParam(VirtualQueryParam[] params, ItemPath propPath) - throws QueryException { - List criterions = new ArrayList(); - - String alias = getContext().getAlias(propPath); - for (VirtualQueryParam param : params) { - Criterion criterion = Restrictions.eq(alias + "." + param.name(), createQueryParamValue(param, propPath)); - criterions.add(criterion); - } - - return andCriterions(criterions); - } - - /** - * This method provides transformation from {@link String} value defined in - * {@link VirtualQueryParam#value()} to real object. Currently only - * to simple types and enum values. - * - * @param param - * @param propPath - * @return real value - * @throws QueryException - */ - private Object createQueryParamValue(VirtualQueryParam param, ItemPath propPath) throws QueryException { - Class type = param.type(); - String value = param.value(); - - try { - if (type.isPrimitive()) { - return type.getMethod("valueOf", new Class[]{String.class}).invoke(null, new Object[]{value}); + protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) { + HibernateQuery hibernateQuery = context.getHibernateQuery(); + EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) + String joinedItemJpaName = joinedItemDefinition.getJpaName(); + String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; + String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); + Condition condition = null; + if (joinedItemDefinition instanceof VirtualCollectionDefinition) { + VirtualCollectionDefinition vcd = (VirtualCollectionDefinition) joinedItemDefinition; + List conditions = new ArrayList<>(vcd.getAdditionalParams().length); + for (VirtualQueryParam vqp : vcd.getAdditionalParams()) { + // e.g. name = "assignmentOwner", type = RAssignmentOwner.class, value = "ABSTRACT_ROLE" + Condition c = Condition.eq(joinedItemAlias + "." + vqp.name(), vqp.value(), vqp.type()); + conditions.add(c); } - - if (type.isEnum()) { - return Enum.valueOf(type, value); + if (conditions.size() > 1) { + condition = Condition.and(conditions); + } else if (conditions.size() == 1) { + condition = conditions.iterator().next(); } - } catch (Exception ex) { - throw new QueryException("Couldn't transform virtual query parameter '" - + param.name() + "' from String to '" + type + "', reason: " + ex.getMessage(), ex); - } - - throw new QueryException("Couldn't transform virtual query parameter '" - + param.name() + "' from String to '" + type + "', it's not yet implemented."); - } - - private void addPathAliasToContext(ItemPath path) { - ItemPath lastPropPath = path.allExceptLast(); - if (ItemPath.EMPTY_PATH.equivalent(lastPropPath)) { - lastPropPath = null; } - - String alias = getContext().getAlias(lastPropPath); - getContext().addAlias(path, alias); + entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); + return joinedItemAlias; } - protected void addNewCriteriaToContext(ItemPath path, Definition def, String realName) { - ItemPath lastPropPath = path.allExceptLast(); - if (ItemPath.EMPTY_PATH.equivalent(lastPropPath)) { - lastPropPath = null; - } + protected String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { + HibernateQuery hibernateQuery = context.getHibernateQuery(); + EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) + String joinedItemJpaName = anyAssociationName; + String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; + String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); - // Virtual path is defined for example for virtual collections. {c:role/c:assignment} and {c:role/c:iducement} - // must use the same criteria, therefore {c:role/assigmnents} is also path under which is this criteria saved. - final ItemPath virtualPath = lastPropPath != null ? new ItemPath(lastPropPath, new QName("", realName)) : - new ItemPath(new QName("", realName)); + Condition condition = Condition.and( + Condition.eq(joinedItemAlias + ".ownerType", ownerType), + Condition.eq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); - Criteria existing = getContext().getCriteria(path); - if (existing != null) { - return; - } - - // If there is already criteria on virtual path, only add new path to aliases and criterias. - Criteria virtualCriteria = getContext().getCriteria(virtualPath); - if (virtualCriteria != null) { - getContext().addAlias(path, virtualCriteria.getAlias()); - getContext().addCriteria(path, virtualCriteria); - return; - } - - // get parent criteria - Criteria pCriteria = getContext().getCriteria(lastPropPath); - - // create new criteria and alias for this relationship - String alias = getContext().addAlias(path, def); - Criteria criteria = pCriteria.createCriteria(realName, alias, JoinType.LEFT_OUTER_JOIN); - getContext().addCriteria(path, criteria); - //also add virtual path to criteria map - getContext().addCriteria(virtualPath, criteria); + entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); + return joinedItemAlias; } - protected Criterion createCriterion(String propertyName, Object value, ValueFilter filter) throws QueryException { + public abstract Condition interpretInternal(String hqlPath) throws QueryException; + + protected Condition createCondition(String propertyName, Object value, ValueFilter filter) throws QueryException { ItemRestrictionOperation operation; if (filter instanceof EqualFilter) { operation = ItemRestrictionOperation.EQ; @@ -455,7 +236,7 @@ protected Criterion createCriterion(String propertyName, Object value, ValueFilt throw new QueryException("Can't translate filter '" + filter + "' to operation."); } - QueryContext2 context = getContext(); + InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); Matcher matcher = interpreter.findMatcher(value); @@ -467,41 +248,6 @@ protected Criterion createCriterion(String propertyName, Object value, ValueFilt return matcher.match(operation, propertyName, value, matchingRule); } - protected List createDefinitionPath(ItemPath path) throws QueryException { - List definitions = new ArrayList(); - if (path == null) { - return definitions; - } - - EntityDefinition lastDefinition = findProperEntityDefinition(path); - for (ItemPathSegment segment : path.getSegments()) { - if (lastDefinition == null) { - break; - } - - if (!(segment instanceof NameItemPathSegment)) { - continue; - } - - NameItemPathSegment named = (NameItemPathSegment) segment; - Definition def = lastDefinition.findDefinition(named.getName(), Definition.class); - definitions.add(def); - - if (def instanceof EntityDefinition) { - lastDefinition = (EntityDefinition) def; - } else if (def instanceof CollectionDefinition) { // todo this seems logical but is it correct? [mederly] - def = ((CollectionDefinition) def).getDefinition(); - if (def instanceof EntityDefinition) { - lastDefinition = ((EntityDefinition) def); - } else { - lastDefinition = null; - } - } - } - - return definitions; - } - protected Object getValue(List values) { if (values == null || values.isEmpty()) { return null; @@ -575,47 +321,28 @@ private Enum getRepoEnumValue(Enum schemaValue, Class repoType) throws QueryExce + schemaValue.getClass() + "'."); } - protected String createPropertyOrReferenceNamePrefix(ItemPath path) throws QueryException { - StringBuilder sb = new StringBuilder(); - - EntityDefinition definition = findProperEntityDefinition(path); - - List segments = path.getSegments(); - for (ItemPathSegment segment : segments) { - QName qname = ItemPath.getName(segment); - if (ObjectType.F_METADATA.equals(qname)) { // todo not QNameUtil.match? [mederly] - continue; - } - if (QNameUtil.match(AssignmentType.F_CONSTRUCTION, qname)) { // ugly hack: construction/resourceRef -> resourceRef - continue; - } - // get entity query definition - Definition childDef = definition.findDefinition(qname, Definition.class); - //todo change this if instanceof and use DefinitionHandler [lazyman] - if (childDef instanceof EntityDefinition) { - EntityDefinition entityDef = (EntityDefinition) childDef; - if (entityDef.isEmbedded()) { - // we don't create new sub criteria, just add dot with jpaName - sb.append(entityDef.getJpaName()); - sb.append('.'); - } - definition = entityDef; - } else if (childDef instanceof CollectionDefinition) { - Definition def = ((CollectionDefinition) childDef).getDefinition(); - if (def instanceof EntityDefinition) { - definition = (EntityDefinition) def; - } - } else if (childDef instanceof PropertyDefinition || childDef instanceof ReferenceDefinition) { - break; - } else { - throw new QueryException("Not implemented yet. Create property name prefix for segment '" - + segment + "', path '" + path + "'."); - } + /** + * Filter of type NOT(PROPERTY=VALUE) causes problems when there are entities with PROPERTY set to NULL. + * + * Such a filter has to be treated like + * + * NOT (PROPERTY=VALUE & PROPERTY IS NOT NULL) + * + * TODO implement for restrictions other than PropertyRestriction. + */ + protected Condition addIsNotNullIfNecessary(Condition condition, String propertyPath) { + if (condition instanceof IsNullCondition || condition instanceof IsNotNullCondition) { + return condition; } - - return sb.toString(); + if (!isNegated()) { + return condition; + } + AndCondition conjunction = new AndCondition(); + conjunction.add(condition); + conjunction.add(new IsNotNullCondition(propertyPath)); + return conjunction; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java index a1da90c6284..f55b6018f03 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java @@ -17,29 +17,10 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; import com.evolveum.midpoint.prism.query.LogicalFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import org.hibernate.criterion.Criterion; /** * @author lazyman */ public abstract class LogicalRestriction extends Restriction { - @Override - public boolean canHandle(ObjectFilter filter) { - if (filter instanceof LogicalFilter) { - return true; - } - - return false; - } - - protected Criterion interpretChildFilter(ObjectFilter filter) throws QueryException { - QueryContext2 context = getContext(); - QueryInterpreter2 interpreter = context.getInterpreter(); - return interpreter.interpretFilter(filter, context, this); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java index a2bda3ead7f..832273b9543 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java @@ -16,17 +16,16 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NaryLogicalFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; -import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.JunctionCondition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Junction; import java.util.ArrayList; import java.util.List; @@ -39,15 +38,6 @@ public abstract class NaryLogicalRestriction extend private static final Trace LOGGER = TraceManager.getTrace(NaryLogicalRestriction.class); private List restrictions; - @Override - public boolean canHandle(ObjectFilter filter) { - if (filter instanceof NaryLogicalFilter) { - return true; - } - - return false; - } - public List getRestrictions() { if (restrictions == null) { restrictions = new ArrayList<>(); @@ -55,7 +45,7 @@ public List getRestrictions() { return restrictions; } - protected void validateFilter(NaryLogicalFilter filter) throws QueryException { + protected void validateFilter() throws QueryException { if (filter.getConditions() == null || filter.getConditions().isEmpty()) { LOGGER.trace("NaryLogicalFilter filter must have at least two conditions in it. " + "Removing logical filter and processing simple condition."); @@ -64,17 +54,14 @@ protected void validateFilter(NaryLogicalFilter filter) throws QueryException { } } - protected Junction updateJunction(List conditions, Junction junction) - throws QueryException { + protected void updateJunction(List subfilters, JunctionCondition junction) throws QueryException { - QueryContext2 context = getContext(); + InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); - for (ObjectFilter condition : conditions) { - Criterion criterion = interpreter.interpretFilter(condition, context, this); - junction.add(criterion); + for (ObjectFilter subfilter : subfilters) { + Condition condition = interpreter.interpretFilter(subfilter, context, this); + junction.add(condition); } - - return junction; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java index f73ff2c3dfc..43729b1342c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java @@ -16,11 +16,13 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.NotCondition; /** * @author lazyman @@ -28,25 +30,9 @@ public class NotRestriction extends UnaryLogicalRestriction { @Override - public boolean canHandle(ObjectFilter filter) { - if (!super.canHandle(filter)) { - return false; - } - - return (filter instanceof NotFilter); - } - - - @Override - public Criterion interpret() throws QueryException { - validateFilter(filter); - Criterion criterion = interpretChildFilter(filter.getFilter()); - - return Restrictions.not(criterion); - } - - @Override - public NotRestriction newInstance() { - return new NotRestriction(); + public Condition interpret() throws QueryException { + validateFilter(); + Condition condition = interpretChildFilter(); + return new NotCondition(condition); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java index ed6ad808e6b..4600fb20c71 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java @@ -16,41 +16,24 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Restrictions; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; /** * @author lazyman + * @author mederly */ public class OrRestriction extends NaryLogicalRestriction { @Override - public boolean canHandle(ObjectFilter filter) { - if (!super.canHandle(filter)) { - return false; - } - - return (filter instanceof OrFilter); - } - - @Override - public Criterion interpret() - throws QueryException { - - validateFilter(filter); - - Disjunction disjunction = Restrictions.disjunction(); + public Condition interpret() throws QueryException { + validateFilter(); + OrCondition disjunction = new OrCondition(); updateJunction(filter.getConditions(), disjunction); - return disjunction; } - - @Override - public OrRestriction newInstance() { - return new OrRestriction(); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java index c50aa0f7c4c..48bd5ca34f6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -19,54 +19,24 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.OrgFilter; -import com.evolveum.midpoint.repo.sql.data.common.RObjectReference; -import com.evolveum.midpoint.repo.sql.data.common.ROrgClosure; import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.util.RUtil; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.DetachedCriteria; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Property; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.Subqueries; -import org.hibernate.type.StringType; -import org.hibernate.type.Type; - -import javax.xml.namespace.QName; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; +import org.hibernate.Query; /** * @author lazyman */ public class OrgRestriction extends Restriction { - private static final String QUERY_PATH = "descendants"; - private static final ItemPath QUERY_ITEM_PATH = new ItemPath(new QName(RUtil.NS_SQL_REPO, QUERY_PATH)); - - private static final String CLOSURE_ALIAS = "closure"; - private static final String DEPTH = CLOSURE_ALIAS + ".depth"; - @Override - public boolean canHandle(ObjectFilter filter) { - if (filter instanceof OrgFilter) { - return true; - } - return false; - } - - @Override - public Criterion interpret() throws QueryException { + public Condition interpret() throws QueryException { if (filter.isRoot()) { -// Criteria pCriteria = getInterpreter().getCriteria(null); - DetachedCriteria dc = DetachedCriteria.forClass(ROrgClosure.class); - String[] strings = new String[1]; - strings[0] = "descendant.oid"; - Type[] type = new Type[1]; - type[0] = StringType.INSTANCE; - dc.setProjection(Projections.sqlGroupProjection("descendant_oid", "descendant_oid having count(descendant_oid)=1", strings, type)); -// pCriteria.add(Subqueries.in("this.oid", dc)); - return Subqueries.propertyIn("oid", dc); -// Query rootOrgQuery = session.createQuery("select org from ROrg as org where org.oid in (select descendant.oid from ROrgClosure group by descendant.oid having count(descendant.oid)=1)"); + // oid in (select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1) + return new InCondition(context.getCurrentHqlPropertyPath() + ".oid", + getSession().createQuery("select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1")); } if (filter.getOrgRef() == null) { @@ -77,30 +47,29 @@ public Criterion interpret() throws QueryException { throw new QueryException("No oid specified in organization reference " + filter.getOrgRef().debugDump()); } - DetachedCriteria detached; + String oidQueryText; // oid in ... switch (filter.getScope()) { case ONE_LEVEL: - detached = DetachedCriteria.forClass(RObjectReference.class, "p"); - detached.add(Restrictions.eq("referenceType", RReferenceOwner.OBJECT_PARENT_ORG)); - detached.setProjection(Projections.distinct(Projections.property("p.ownerOid"))); - detached.add(Restrictions.eq("p.targetOid", filter.getOrgRef().getOid())); + oidQueryText = + "select ref.ownerOid " + // TODO distinct(ref.ownerOid) ? (was in original QueryInterpreter) + "from RObjectReference ref " + + "where " + + "ref.referenceType = " + nameOf(RReferenceOwner.OBJECT_PARENT_ORG) + " and " + + "ref.targetOid = :orgOid"; break; case SUBTREE: default: - detached = DetachedCriteria.forClass(RObjectReference.class, "p"); - detached.add(Restrictions.eq("referenceType", RReferenceOwner.OBJECT_PARENT_ORG)); - detached.setProjection(Projections.distinct(Projections.property("p.ownerOid"))); - detached.add(Property.forName("targetOid").in( - DetachedCriteria.forClass(ROrgClosure.class, "cl") - .setProjection(Projections.property("cl.descendantOid")) - .add(Restrictions.eq("cl.ancestorOid", filter.getOrgRef().getOid())))); + oidQueryText = + "select ref.ownerOid " + + "from RObjectReference ref " + + "where " + + "ref.referenceType = " + nameOf(RReferenceOwner.OBJECT_PARENT_ORG) + " and " + + "ref.targetOid in (" + + "select descendantOid from ROrgClosure where ancestorOid = :orgOid"; } - String mainAlias = getContext().getAlias(null); - return Subqueries.propertyIn(mainAlias + ".oid", detached); + Query oidQuery = getSession().createQuery(oidQueryText); + oidQuery.setParameter("orgOid", filter.getOrgRef().getOid()); + return new InCondition(context.getCurrentHqlPropertyPath() + ".oid", oidQuery); } - @Override - public OrgRestriction newInstance() { - return new OrgRestriction(); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index e9ff2df30e1..ae2fe5df831 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -16,16 +16,14 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import org.apache.commons.lang.StringUtils; -import org.hibernate.criterion.Criterion; +import org.apache.commons.lang.Validate; /** * @author lazyman @@ -34,50 +32,25 @@ public class PropertyRestriction extends ItemRestriction { private static final Trace LOGGER = TraceManager.getTrace(PropertyRestriction.class); - @Override - public boolean canHandle(ObjectFilter filter) throws QueryException { - if (!super.canHandle(filter)) { - return false; - } - - ValueFilter valFilter = (ValueFilter) filter; - ItemPath fullPath = valFilter.getFullPath(); + PropertyDefinition propertyDefinition; - PropertyDefinition def = findProperDefinition(fullPath, PropertyDefinition.class); - return def != null; + public PropertyRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition, PropertyDefinition propertyDefinition) { + super(rootEntityDefinition, startPropertyPath, startEntityDefinition); + Validate.notNull(propertyDefinition); + this.propertyDefinition = propertyDefinition; } @Override - public Criterion interpretInternal(ValueFilter filter) - throws QueryException { - QueryContext2 context = getContext(); + public Condition interpretInternal(String hqlPath) throws QueryException { - ItemPath fullPath = filter.getFullPath(); - PropertyDefinition def = findProperDefinition(fullPath, PropertyDefinition.class); - if (def.isLob()) { - throw new QueryException("Can't query based on clob property value '" + def + "'."); + if (propertyDefinition.isLob()) { + throw new QueryException("Can't query based on clob property value '" + propertyDefinition + "'."); } - String propertyName = def.getJpaName(); - String alias = context.getAlias(filter.getParentPath()); - - StringBuilder sb = new StringBuilder(); - if (StringUtils.isNotEmpty(alias)) { - sb.append(alias); - sb.append('.'); - } - sb.append(createPropertyOrReferenceNamePrefix(fullPath)); - sb.append(propertyName); + String propertyFullName = hqlPath + "." + propertyDefinition.getJpaName(); + Object value = getValueFromFilter(filter, propertyDefinition); + Condition condition = createCondition(propertyFullName, value, filter); - Object value = getValueFromFilter(filter, def); - - String propertyPath = sb.toString(); - Criterion criterion = createCriterion(propertyPath, value, filter); - return addIsNotNullIfNecessary(criterion, propertyPath); - } - - @Override - public PropertyRestriction newInstance() { - return new PropertyRestriction(); + return addIsNotNullIfNecessary(condition, propertyFullName); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index e516edaffd1..0ed955e51f4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -21,13 +21,17 @@ import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext.ProperDefinitionSearchResult; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.QNameUtil; @@ -46,19 +50,14 @@ */ public class ReferenceRestriction extends ItemRestriction { - @Override - public boolean canHandle(ObjectFilter filter) { - if (filter instanceof RefFilter) { - return true; - } - return false; + public ReferenceRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { + super(rootEntityDefinition, startPropertyPath, startEntityDefinition); } // modelled after PropertyRestriction.interpretInternal, with some differences @Override - public Criterion interpretInternal(RefFilter filter) throws QueryException { + public Condition interpretInternal(String hqlPath) throws QueryException { - // let's check the value (null is not supported yet) List values = filter.getValues(); if (values != null && values.size() > 1) { throw new QueryException("Ref filter '" + filter + "' contain more than one reference value (which is not supported for now)."); @@ -68,43 +67,15 @@ public Criterion interpretInternal(RefFilter filter) throws QueryException { refValue = (PrismReferenceValue) values.get(0); } - QueryContext2 context = getContext(); - - ItemPath fullPath = filter.getFullPath(); - // actually, we cannot look for ReferenceDefinition here, because e.g. linkRef has a CollectionDefinition - Definition def = findProperDefinition(fullPath, Definition.class); - if (def == null) { + InterpretationContext context = getContext(); + ItemPath fullPath = getFullPath(filter.getPath()); + ProperDefinitionSearchResult defResult = context.findProperDefinition(fullPath, Definition.class); + if (defResult == null || defResult.getItemDefinition() == null) { throw new QueryException("Definition for " + fullPath + " couldn't be found."); } + Definition definition = defResult.getItemDefinition(); // actually, we cannot expect ReferenceDefinition here, because e.g. linkRef has a CollectionDefinition - // ugly hacking, todo refactor! - StringBuilder sb = new StringBuilder(); - if (def instanceof ReferenceDefinition) { - ItemPath parentPath = filter.getParentPath(); - // hack: construction/resourceRef->resourceRef - if (QNameUtil.match(ConstructionType.F_RESOURCE_REF, filter.getElementName()) && - parentPath != null && parentPath.last() instanceof NameItemPathSegment && - QNameUtil.match(AssignmentType.F_CONSTRUCTION, ((NameItemPathSegment) parentPath.last()).getName())) { - parentPath = parentPath.allExceptLast(); - } - String alias = context.getAlias(parentPath); - if (StringUtils.isNotEmpty(alias)) { - sb.append(alias); - sb.append('.'); - } - sb.append(createPropertyOrReferenceNamePrefix(filter.getPath())); // i'm not sure about this [mederly] - String referenceName = def.getJpaName(); - sb.append(referenceName); - sb.append("."); - } else { - String alias = context.getAlias(filter.getPath()); - if (StringUtils.isNotEmpty(alias)) { - sb.append(alias); - sb.append('.'); - } - sb.append(createPropertyOrReferenceNamePrefix(filter.getPath())); // i'm not sure about this [mederly] - } - String prefix = sb.toString(); + String propertyFullNamePrefix = hqlPath + "." + definition.getJpaName() + "."; String refValueOid = null; QName refValueRelation = null; @@ -114,22 +85,22 @@ public Criterion interpretInternal(RefFilter filter) throws QueryException { refValueRelation = refValue.getRelation(); refValueTargetType = refValue.getTargetType(); } - Conjunction conjunction = Restrictions.conjunction(); - conjunction.add(handleEqOrNull(prefix + ObjectReference.F_TARGET_OID, refValueOid)); + AndCondition conjunction = Condition.and(); + conjunction.add(handleEqOrNull(propertyFullNamePrefix + ObjectReference.F_TARGET_OID, refValueOid)); if (refValueOid != null) { if (refValueRelation == null) { // Return only references without relation - conjunction.add(Restrictions.eq(prefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); + conjunction.add(Condition.eq(propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); } else if (refValueRelation.equals(PrismConstants.Q_ANY)) { // Return all relations => no restriction } else { // return references with specific relation - conjunction.add(handleEqOrNull(prefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); + conjunction.add(handleEqOrNull(propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); } if (refValueTargetType != null) { - conjunction.add(handleEqOrNull(prefix + ObjectReference.F_TYPE, + conjunction.add(handleEqOrNull(propertyFullNamePrefix + ObjectReference.F_TYPE, ClassMapper.getHQLTypeForQName(refValueTargetType))); } } @@ -139,16 +110,12 @@ public Criterion interpretInternal(RefFilter filter) throws QueryException { return conjunction; } - @Override - public ReferenceRestriction newInstance() { - return new ReferenceRestriction(); - } - private Criterion handleEqOrNull(String propertyName, Object value) { + private Condition handleEqOrNull(String propertyName, Object value) { if (value == null) { - return Restrictions.isNull(propertyName); + return Condition.isNull(propertyName); + } else { + return Condition.eq(propertyName, value); } - - return Restrictions.eq(propertyName, value); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index 7fd9b471bd8..3a92703fd56 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -16,23 +16,31 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.NotNullExpression; -import org.hibernate.criterion.NullExpression; -import org.hibernate.criterion.Restrictions; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; +import org.hibernate.Session; + +import java.util.List; /** + * An image of an ObjectFilter, forming a restriction tree. + * Preserves some state related to the interpretation (translation). + * Provides functionality related to the translation. + * * @author lazyman + * @author mederly */ public abstract class Restriction { - protected QueryContext2 context; + protected InterpretationContext context; protected Restriction parent; protected T filter; @@ -44,14 +52,18 @@ public void setFilter(T filter) { this.filter = filter; } - public QueryContext2 getContext() { + public InterpretationContext getContext() { return context; } - public void setContext(QueryContext2 context) { + public void setContext(InterpretationContext context) { this.context = context; } + public Session getSession() { + return context.getSession(); + } + public Restriction getParent() { return parent; } @@ -60,37 +72,42 @@ public void setParent(Restriction parent) { this.parent = parent; } - public abstract Criterion interpret() throws QueryException; - - public abstract boolean canHandle(ObjectFilter filter) throws QueryException; - - // todo don't know if cloning is necessary... [lazyman] - // this can be replaced probably by simple java reflection call - public abstract Restriction newInstance(); + public abstract Condition interpret() throws QueryException; protected boolean isNegated() { return filter instanceof NotFilter || (parent != null && parent.isNegated()); } + protected String nameOf(Enum e) { + return e.getClass().getName() + "." + e.name(); + } + /** - * Filter of type NOT(PROPERTY=VALUE) causes problems when there are entities with PROPERTY set to NULL. + * Returns the item path that is the "base" path for any child restrictions. + * Default is the empty path. * - * Such a filter has to be treated like - * - * NOT (PROPERTY=VALUE & PROPERTY IS NOT NULL) - * - * TODO implement for restrictions other than PropertyRestriction. + * Currently, only the ForValue filter/restriction changes this path. E.g. for UserType: ForValue (assignment) + * changes the base path for its children to "assignment". */ - protected Criterion addIsNotNullIfNecessary(Criterion criterion, String propertyPath) { - if (criterion instanceof NullExpression || criterion instanceof NotNullExpression) { - return criterion; + public ItemPath getItemPathForChildren() { + if (parent != null) { + return parent.getItemPathForChildren(); // by default, restrictions don't change the reference path + } else { + return ItemPath.EMPTY_PATH; } - if (!isNegated()) { - return criterion; - } - Conjunction conjunction = Restrictions.conjunction(); - conjunction.add(criterion); - conjunction.add(Restrictions.isNotNull(propertyPath)); - return conjunction; } + + /** + * Given the (relative) path, returns full path of an item to be used in a restriction. + * + * @param path + * @return + */ + protected ItemPath getFullPath(ItemPath path) { + if (parent != null) { + return new ItemPath(parent.getItemPathForChildren(), path); + } else { + return path; + } + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java index 01fdc0133df..87b09d21646 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -16,13 +16,18 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; -import com.evolveum.midpoint.repo.sql.query2.QueryContext2; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.EqualsCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Restrictions; @@ -38,27 +43,27 @@ public class TypeRestriction extends Restriction { @Override - public Criterion interpret() throws QueryException { - String property = getContext().getAlias(null) + "." + RObject.F_OBJECT_TYPE_CLASS; + public Condition interpret() throws QueryException { + String property = getContext().getCurrentHqlPropertyPath() + "." + RObject.F_OBJECT_TYPE_CLASS; Set values = getValues(filter.getType()); - Criterion basedOnType; + Condition basedOnType; if (values.size() > 1) { - basedOnType = Restrictions.in(property, values); + basedOnType = new InCondition(property, values); } else { - basedOnType = Restrictions.eq(property, values.iterator().next()); + basedOnType = new EqualsCondition(property, values.iterator().next()); } if (filter.getFilter() == null) { return basedOnType; } - QueryContext2 context = getContext(); + InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); - Criterion basedOnFilter = interpreter.interpretFilter(filter.getFilter(), context, this); + Condition basedOnFilter = interpreter.interpretFilter(filter.getFilter(), context, this); - return Restrictions.and(basedOnType, basedOnFilter); + return new AndCondition(basedOnType, basedOnFilter); } private Set getValues(QName typeQName) { @@ -83,16 +88,4 @@ private Set getValues(QName typeQName) { return set; } - @Override - public boolean canHandle(ObjectFilter filter) throws QueryException { - if (filter instanceof TypeFilter) { - return true; - } - return false; - } - - @Override - public Restriction newInstance() { - return new TypeRestriction(); - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java index 8ac321ff9aa..c9204703543 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java @@ -16,9 +16,11 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.UnaryLogicalFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -29,16 +31,13 @@ public abstract class UnaryLogicalRestriction exte private static final Trace LOGGER = TraceManager.getTrace(UnaryLogicalRestriction.class); - @Override - public boolean canHandle(ObjectFilter filter) { - if (filter instanceof UnaryLogicalFilter) { - return true; - } - - return false; + protected Condition interpretChildFilter() throws QueryException { + InterpretationContext context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + return interpreter.interpretFilter(filter.getFilter(), context, this); } - protected void validateFilter(UnaryLogicalFilter filter) throws QueryException { + protected void validateFilter() throws QueryException { if (filter.getFilter() == null) { LOGGER.trace("UnaryLogicalFilter filter must have child filter defined in it."); throw new QueryException("UnaryLogicalFilter '" + filter.debugDump() From 379e680a68c39f46116d3b811939e1224c2a4469 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 21 Nov 2015 13:19:32 +0100 Subject: [PATCH 011/116] Compilable state. --- .../sql/query2/InterpretationContext.java | 147 ++++++++------- .../query2/ProperDefinitionSearchResult.java | 41 +++++ .../repo/sql/query2/QueryEngine2.java | 5 +- .../repo/sql/query2/QueryInterpreter2.java | 30 +-- .../repo/sql/query2/hqm/HibernateQuery.java | 72 +++++--- ...ondition.java => QueryParameterValue.java} | 25 ++- .../sql/query2/hqm/RootHibernateQuery.java | 174 ++++++++++++++++++ .../query2/hqm/condition/AndCondition.java | 18 +- .../sql/query2/hqm/condition/Condition.java | 66 ++----- .../hqm/condition/HibernateSubquery.java | 41 +++++ .../sql/query2/hqm/condition/InCondition.java | 29 ++- .../hqm/condition/IsNotNullCondition.java | 13 +- .../query2/hqm/condition/IsNullCondition.java | 14 +- .../hqm/condition/JunctionCondition.java | 37 +++- .../query2/hqm/condition/NotCondition.java | 15 +- .../sql/query2/hqm/condition/OrCondition.java | 12 ++ .../hqm/condition/PropertyCondition.java | 23 ++- .../condition/SimpleComparisonCondition.java | 63 +++++++ .../sql/query2/matcher/DefaultMatcher.java | 5 +- .../repo/sql/query2/matcher/Matcher.java | 49 +++-- .../sql/query2/matcher/PolyStringMatcher.java | 17 +- .../sql/query2/matcher/StringMatcher.java | 5 +- .../query2/restriction/AndRestriction.java | 2 +- .../query2/restriction/InOidRestriction.java | 2 +- .../query2/restriction/ItemRestriction.java | 53 ++++-- .../query2/restriction/NotRestriction.java | 2 +- .../sql/query2/restriction/OrRestriction.java | 2 +- .../query2/restriction/OrgRestriction.java | 20 +- .../restriction/ReferenceRestriction.java | 30 ++- .../query2/restriction/TypeRestriction.java | 22 +-- .../midpoint/repo/sql/util/ClassMapper.java | 12 ++ 31 files changed, 774 insertions(+), 272 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/{condition/EqualsCondition.java => QueryParameterValue.java} (62%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index cd7c0e6af0d..f481d0eec15 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -19,49 +19,57 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.restriction.TypeRestriction; import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.apache.commons.lang.StringUtils; -import org.hibernate.Criteria; +import org.apache.commons.lang.Validate; import org.hibernate.Session; -import javax.xml.namespace.QName; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; /** * @author lazyman + * @author mederly */ public class InterpretationContext { + private static final Trace LOGGER = TraceManager.getTrace(InterpretationContext.class); + private QueryInterpreter2 interpreter; private PrismContext prismContext; private Session session; private Class type; - private HibernateQuery hibernateQuery; + private RootHibernateQuery hibernateQuery; // path from the root filter to the current one (necessary when finding correct Restriction) private List currentFilterPath = new ArrayList<>(); public InterpretationContext(QueryInterpreter2 interpreter, Class type, - PrismContext prismContext, Session session) { + PrismContext prismContext, Session session) throws QueryException { + + Validate.notNull(interpreter, "interpreter"); + Validate.notNull(type, "type"); + Validate.notNull(prismContext, "prismContext"); + Validate.notNull(session, "session"); + this.interpreter = interpreter; this.type = type; this.prismContext = prismContext; @@ -69,8 +77,16 @@ public InterpretationContext(QueryInterpreter2 interpreter, Class getType() { return type; } - public HibernateQuery getHibernateQuery() { + public RootHibernateQuery getHibernateQuery() { return hibernateQuery; } - public static class ProperDefinitionSearchResult { - EntityDefinition rootEntityDefinition; - T itemDefinition; - - public ProperDefinitionSearchResult(EntityDefinition rootEntityDefinition, T itemDefinition) { - this.rootEntityDefinition = rootEntityDefinition; - this.itemDefinition = itemDefinition; - } - - public EntityDefinition getRootEntityDefinition() { - return rootEntityDefinition; - } - - public T getItemDefinition() { - return itemDefinition; - } - } - + /** + * Finds the proper definition for (possibly abstract) type. + * If the type is abstract, tries types which could be used in the query (types that have the item definition). + * + * It should try more abstract types first, in order to allow for later narrowing. (This would not work in case + * of double narrowing to an item that has the same name in two different subclasses - but currently we don't know + * of such.) + * + * @param path Path to be found + * @param clazz Kind of definition to be looked for + * @return Entity type definition + item definition + */ public ProperDefinitionSearchResult findProperDefinition(ItemPath path, Class clazz) { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); Class objectClass = getType(); @@ -122,7 +132,7 @@ public ProperDefinitionSearchResult findProperDefiniti //we should try to find property in descendant classes for (Class type : findOtherPossibleParents()) { - EntityDefinition entityDefinition = registry.findDefinition(getType(), null, EntityDefinition.class); + EntityDefinition entityDefinition = registry.findDefinition(type, null, EntityDefinition.class); T pathDefinition = entityDefinition.findDefinition(path, clazz); if (pathDefinition != null) { return new ProperDefinitionSearchResult<>(entityDefinition, pathDefinition); @@ -131,53 +141,58 @@ public ProperDefinitionSearchResult findProperDefiniti return null; } + /** + * Similar to the above, but returns only the entity name. + * @param path + * @return + */ protected EntityDefinition findProperEntityDefinition(ItemPath path) { - QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - if (!ObjectType.class.equals(getType())) { - return registry.findDefinition(getType(), null, EntityDefinition.class); - } - - EntityDefinition entity = null; - // we should try to find property in descendant classes - for (Class type : findOtherPossibleParents()) { - entity = registry.findDefinition(type, null, EntityDefinition.class); - Definition def = entity.findDefinition(path, Definition.class); - if (def != null) { - break; - } + ProperDefinitionSearchResult result = findProperDefinition(path, Definition.class); + if (result != null) { + return result.getRootEntityDefinition(); + } else { + return null; } - LOGGER.trace("Found proper entity definition for path {}, {}", path, entity.toString()); - return entity; } - private Set> findOtherPossibleParents() { - TypeRestriction typeRestriction = findTypeRestrictionParent(this); + private List> findOtherPossibleParents() { + TypeFilter typeFilter = findTypeFilterParent(); ObjectTypes typeClass; - if (typeRestriction != null) { - TypeFilter filter = typeRestriction.getFilter(); - typeClass = ObjectTypes.getObjectTypeFromTypeQName(filter.getType()); + if (typeFilter != null) { + typeClass = ObjectTypes.getObjectTypeFromTypeQName(typeFilter.getType()); } else { typeClass = ObjectTypes.getObjectType(getType()); } - Set> classes = new HashSet<>(); - classes.add(typeClass.getClassDefinition()); - - switch (typeClass) { - case OBJECT: - classes.addAll(ObjectTypes.getAllObjectTypes()); - break; - case FOCUS_TYPE: - classes.add(UserType.class); - case ABSTRACT_ROLE: - classes.add(RoleType.class); - classes.add(OrgType.class); + List> classes = new ArrayList<>(); + classes.add(typeClass.getClassDefinition()); // abstract one has to go first + + if (typeClass == ObjectTypes.OBJECT) { + classes.addAll(ObjectTypes.getAllObjectTypes()); + } else if (typeClass == ObjectTypes.FOCUS_TYPE) { + classes.add(UserType.class); + classes.add(AbstractRoleType.class); + classes.add(RoleType.class); + classes.add(OrgType.class); + } else if (typeClass == ObjectTypes.ABSTRACT_ROLE) { + classes.add(RoleType.class); + classes.add(OrgType.class); } - LOGGER.trace("Found possible parents {} for entity definitions.", Arrays.toString(classes.toArray())); + LOGGER.trace("Found possible parents {} for entity definitions.", classes); return classes; } + private TypeFilter findTypeFilterParent() { + for (int i = currentFilterPath.size()-1; i >= 0; i--) { + ObjectFilter filter = currentFilterPath.get(i); + if (filter instanceof TypeFilter) { + return (TypeFilter) filter; + } + } + return null; + } + public void pushFilter(ObjectFilter filter) { currentFilterPath.add(filter); } @@ -187,10 +202,8 @@ public void popFilter() { } public String getCurrentHqlPropertyPath() { - // TODO + // preliminary implementation: returns root alias (should be changed when ForValue is implemented) + return hibernateQuery.getPrimaryEntityAlias(); } - private void getCurrentItemPath() { - - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java new file mode 100644 index 00000000000..a17faacff16 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; + +/** + * @author Pavol + */ +public class ProperDefinitionSearchResult { + EntityDefinition rootEntityDefinition; + T itemDefinition; + + public ProperDefinitionSearchResult(EntityDefinition rootEntityDefinition, T itemDefinition) { + this.rootEntityDefinition = rootEntityDefinition; + this.itemDefinition = itemDefinition; + } + + public EntityDefinition getRootEntityDefinition() { + return rootEntityDefinition; + } + + public T getItemDefinition() { + return itemDefinition; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java index 7fde62d2e23..4c300deb7ae 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java @@ -23,6 +23,7 @@ import com.evolveum.midpoint.repo.sql.query.RQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; @@ -51,13 +52,13 @@ public RQuery interpret(ObjectQuery query, Class type, boolean countingObjects, Session session) throws QueryException { QueryInterpreter2 interpreter = new QueryInterpreter2(repoConfiguration); - HibernateQuery hibernateQuery = interpreter.interpret(query, type, options, prismContext, countingObjects, session); + RootHibernateQuery hibernateQuery = interpreter.interpret(query, type, options, prismContext, countingObjects, session); if (countingObjects) { hibernateQuery.addProjectionElement(new ProjectionElement("count(*)")); } else { hibernateQuery.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); } - return new RQueryImpl(hibernateQuery.getAsHql()); + return new RQueryImpl(hibernateQuery.getAsHqlQuery(session)); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index cce1277fa74..cb401e19549 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -44,6 +44,7 @@ import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.matcher.DefaultMatcher; import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; @@ -53,6 +54,7 @@ import com.evolveum.midpoint.repo.sql.query2.restriction.AnyPropertyRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.CollectionRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.InOidRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; import com.evolveum.midpoint.repo.sql.query2.restriction.NotRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.OrRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.OrgRestriction; @@ -75,7 +77,6 @@ import java.util.Map; import static com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl.ObjectPagingAfterOid; -import static com.evolveum.midpoint.repo.sql.query2.InterpretationContext.ProperDefinitionSearchResult; /** * Interprets midPoint queries by translating them to hibernate (HQL) ones. @@ -130,9 +131,9 @@ public SqlRepositoryConfiguration getRepoConfiguration() { return repoConfiguration; } - public HibernateQuery interpret(ObjectQuery query, Class type, - Collection> options, PrismContext prismContext, - boolean countingObjects, Session session) throws QueryException { + public RootHibernateQuery interpret(ObjectQuery query, Class type, + Collection> options, PrismContext prismContext, + boolean countingObjects, Session session) throws QueryException { Validate.notNull(type, "Type must not be null."); Validate.notNull(session, "Session must not be null."); Validate.notNull(prismContext, "Prism context must not be null."); @@ -146,7 +147,7 @@ public HibernateQuery interpret(ObjectQuery query, Class t interpretQueryFilter(query, context); interpretPagingAndSorting(query, context, countingObjects); - HibernateQuery hibernateQuery = context.getHibernateQuery(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); if (!countingObjects) { String rootAlias = hibernateQuery.getPrimaryEntityAlias(); @@ -165,9 +166,9 @@ public HibernateQuery interpret(ObjectQuery query, Class t private void interpretQueryFilter(ObjectQuery query, InterpretationContext context) throws QueryException { try { - HibernateQuery hibernateQuery = context.getHibernateQuery(); if (query != null && query.getFilter() != null) { Condition c = interpretFilter(query.getFilter(), context, null); + HibernateQuery hibernateQuery = context.getHibernateQuery(); hibernateQuery.addCondition(c); } } catch (QueryException ex) { @@ -249,13 +250,14 @@ private Restriction findAndCreateRestriction(T filter, } private void interpretPagingAndSorting(ObjectQuery query, InterpretationContext context, boolean countingObjects) { - HibernateQuery hibernateQuery = context.getHibernateQuery(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String rootAlias = hibernateQuery.getPrimaryEntityAlias(); if (query != null && query.getPaging() instanceof ObjectPagingAfterOid) { ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); if (paging.getOidGreaterThan() != null) { - hibernateQuery.addCondition(Condition.gt(rootAlias + ".oid", paging.getOidGreaterThan())); + Condition c = hibernateQuery.createSimpleComparisonCondition(rootAlias + ".oid", paging.getOidGreaterThan(), ">"); + hibernateQuery.addCondition(c); } } @@ -268,18 +270,18 @@ private void interpretPagingAndSorting(ObjectQuery query, InterpretationContext } } - protected void updatePagingAndSortingByOid(HibernateQuery hibernateQuery, ObjectPagingAfterOid paging) { + protected void updatePagingAndSortingByOid(RootHibernateQuery hibernateQuery, ObjectPagingAfterOid paging) { String rootAlias = hibernateQuery.getPrimaryEntityAlias(); if (paging.getOrderBy() != null || paging.getDirection() != null || paging.getOffset() != null) { throw new IllegalArgumentException("orderBy, direction nor offset is allowed on ObjectPagingAfterOid"); } - hibernateQuery.addOrder(rootAlias + ".oid", OrderDirection.ASCENDING); + hibernateQuery.setOrder(rootAlias + ".oid", OrderDirection.ASCENDING); if (paging.getMaxSize() != null) { hibernateQuery.setMaxResults(paging.getMaxSize()); } } - public void updatePagingAndSorting(HibernateQuery hibernateQuery, Class type, ObjectPaging paging) { + public void updatePagingAndSorting(RootHibernateQuery hibernateQuery, Class type, ObjectPaging paging) { if (paging == null) { return; } @@ -316,14 +318,14 @@ public void updatePagingAndSorting(HibernateQuery hiberna if (paging.getDirection() != null) { switch (paging.getDirection()) { case ASCENDING: - hibernateQuery.addOrder(propertyName, OrderDirection.ASCENDING); + hibernateQuery.setOrder(propertyName, OrderDirection.ASCENDING); break; case DESCENDING: - hibernateQuery.addOrder(propertyName, OrderDirection.DESCENDING); + hibernateQuery.setOrder(propertyName, OrderDirection.DESCENDING); break; } } else { - hibernateQuery.addOrder(propertyName, OrderDirection.ASCENDING); + hibernateQuery.setOrder(propertyName, OrderDirection.ASCENDING); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index 9b265c4f994..81b7240b4c9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -17,21 +17,29 @@ package com.evolveum.midpoint.repo.sql.query2.hqm; import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryDefinitionRegistry2; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import org.apache.commons.lang.Validate; import org.hibernate.Query; import org.hibernate.transform.ResultTransformer; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Query in HQL that is being created. * * @author mederly */ -public class HibernateQuery { +public abstract class HibernateQuery { private static final String INDENT_STRING = " "; @@ -46,7 +54,7 @@ public class HibernateQuery { * RUser u * left join u.assignments a with ... */ - private EntityReference primaryEntity; + private EntityReference primaryEntity; // not null /** * All other entities for this query, again along with joined entities. @@ -65,9 +73,12 @@ public class HibernateQuery { */ private List conditions = new ArrayList<>(); + private String orderByProperty; + private OrderDirection orderDirection; + public HibernateQuery(EntityDefinition primaryEntityDef) { - EntityReference primaryEntity = createItemSpecification(primaryEntityDef); - setPrimaryEntity(primaryEntity); + Validate.notNull(primaryEntityDef, "primaryEntityDef"); + primaryEntity = createItemSpecification(primaryEntityDef); } public List getProjectionElements() { @@ -94,24 +105,39 @@ public void addCondition(Condition condition) { conditions.add(condition); } - public Query getAsHql() { + public String getAsHqlText(int indent) { StringBuilder sb = new StringBuilder(); + indent(sb, indent); sb.append("select\n"); - ProjectionElement.dumpToHql(sb, projectionElements, 1); // we finish at the end of the last line (not at the new line) + ProjectionElement.dumpToHql(sb, projectionElements, indent + 1); // we finish at the end of the last line (not at the new line) sb.append("\n"); + indent(sb, indent); sb.append("from\n"); - primaryEntity.dumpToHql(sb, 1); + primaryEntity.dumpToHql(sb, indent + 1); for (EntityReference otherEntity : otherEntities) { sb.append(",\n"); - otherEntity.dumpToHql(sb, 1); + otherEntity.dumpToHql(sb, indent+1); } - sb.append("\n"); if (!conditions.isEmpty()) { + sb.append("\n"); + indent(sb, indent); sb.append("where\n"); - Condition.dumpToHql(sb, conditions, 1); + Condition.dumpToHql(sb, conditions, indent+1); + } + if (orderByProperty != null) { + sb.append("\n"); + indent(sb, indent); + sb.append("order by ").append(orderByProperty); + if (orderDirection != null) { + switch (orderDirection) { + case DESCENDING: sb.append(" desc"); break; + case ASCENDING: sb.append(" asc"); break; + default: throw new IllegalStateException("Unknown ordering: " + orderDirection); + } + } } return sb.toString(); } @@ -140,7 +166,7 @@ public String createAlias(String name, boolean isEntity) { int prefixIndex = isEntity ? 1 : 0; prefix = Character.toString(name.charAt(prefixIndex)).toLowerCase(); - int index = 1; + int index = 2; String alias = prefix; while (hasAlias(alias)) { alias = prefix + Integer.toString(index); @@ -171,19 +197,21 @@ public String getPrimaryEntityAlias() { return getPrimaryEntity().getAlias(); } - public void addOrder(String propertyPath, OrderDirection direction) { - // TODO + public void setOrder(String propertyPath, OrderDirection direction) { + this.orderByProperty = propertyPath; + this.orderDirection = direction; } - public void setMaxResults(Integer size) { - - } - - public void setFirstResult(Integer offset) { - - } - - public void setResultTransformer(ResultTransformer resultTransformer) { + public abstract RootHibernateQuery getRootQuery(); + // used to narrow the primary entity e.g. from RObject to RUser (e.g. during ItemRestriction processing) + public void narrowPrimaryEntity(EntityDefinition newDefinition) throws QueryException { + String oldEntityName = getPrimaryEntity().getName(); + Class oldEntityClass = ClassMapper.getHqlClassForHqlName(oldEntityName); + Class newEntityClass = newDefinition.getJpaType(); + if (!(oldEntityClass.isAssignableFrom(newEntityClass))) { + throw new QueryException("Cannot narrow primary entity definition from " + oldEntityClass + " to " + newEntityClass); + } + getPrimaryEntity().setName(newDefinition.getJpaName()); // alias stays the same } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java similarity index 62% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java index 23534d72792..053cd79540b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/EqualsCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java @@ -14,21 +14,32 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +package com.evolveum.midpoint.repo.sql.query2.hqm; -import org.hibernate.Query; - -import java.util.Collection; +import org.hibernate.type.Type; /** * @author mederly */ -public class EqualsCondition extends PropertyCondition { +public class QueryParameterValue { private Object value; + private Type type; + + public QueryParameterValue(Object value, Type type) { + this.value = value; + this.type = type; + } - public EqualsCondition(String propertyPath, Object value) { - super(propertyPath); + public QueryParameterValue(Object value) { this.value = value; } + + public Type getType() { + return type; + } + + public Object getValue() { + return value; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java new file mode 100644 index 00000000000..9f4fd41e45f --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm; + +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.NotCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.SimpleComparisonCondition; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.criterion.MatchMode; +import org.hibernate.transform.ResultTransformer; +import org.hibernate.type.Type; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author mederly + */ +public class RootHibernateQuery extends HibernateQuery { + + private Map parameters = new HashMap<>(); + private Integer maxResults; + private Integer firstResult; + private ResultTransformer resultTransformer; + + public RootHibernateQuery(EntityDefinition primaryEntityDef) { + super(primaryEntityDef); + } + + public String addParameter(String prefix, Object value, Type type) { + String name = findFreeName(prefix); + parameters.put(name, new QueryParameterValue(value, type)); + return name; + } + + public String addParameter(String prefix, Object value) { + return addParameter(prefix, value, null); + } + + private String findFreeName(String prefix) { + int i = 1; + for (;;) { + String name = i == 1 ? prefix : prefix+i; + if (!parameters.containsKey(name)) { + return name; + } + i++; + } + } + + public Query getAsHqlQuery(Session session) { + String text = getAsHqlText(0); + Query query = session.createQuery(text); + for (Map.Entry parameter : parameters.entrySet()) { + String name = parameter.getKey(); + QueryParameterValue parameterValue = parameter.getValue(); + if (parameterValue.getType() != null) { + query.setParameter(name, parameterValue.getValue(), parameterValue.getType()); + } else { + query.setParameter(name, parameterValue.getValue()); + } + } + if (maxResults != null) { + query.setMaxResults(maxResults); + } + if (firstResult != null) { + query.setFirstResult(firstResult); + } + if (resultTransformer != null) { + query.setResultTransformer(resultTransformer); + } + return query; + } + + @Override + public RootHibernateQuery getRootQuery() { + return this; + } + + public void setMaxResults(Integer size) { + this.maxResults = size; + } + + public void setFirstResult(Integer offset) { + this.firstResult = offset; + } + + public void setResultTransformer(ResultTransformer resultTransformer) { + this.resultTransformer = resultTransformer; + } + + public Condition createIsNull(String propertyPath) { + return new IsNullCondition(this, propertyPath); + } + + public Condition createIsNotNull(String propertyPath) { + return new IsNotNullCondition(this, propertyPath); + } + + public Condition createEq(String propertyPath, Object value, boolean ignoreCase) { + return createSimpleComparisonCondition(propertyPath, value, "=", ignoreCase); + } + + public Condition createEq(String propertyPath, Object value) { + return createEq(propertyPath, value, false); + } + + public Condition createSimpleComparisonCondition(String propertyPath, Object value, String comparatorSymbol) { + return new SimpleComparisonCondition(this, propertyPath, value, comparatorSymbol, false); + } + + public Condition createSimpleComparisonCondition(String propertyPath, Object value, String comparatorSymbol, boolean ignoreCase) { + return new SimpleComparisonCondition(this, propertyPath, value, comparatorSymbol, ignoreCase); + } + + public Condition createLike(String propertyPath, String value, MatchMode matchMode, boolean ignoreCase) { + switch (matchMode) { + case ANYWHERE: value = "%" + value + "%"; break; + case START: value = value + "%"; break; + case END: value = "%" + value; break; + default: throw new IllegalStateException("Unsupported match mode: " + matchMode); + } + return new SimpleComparisonCondition(this, propertyPath, value, "like", ignoreCase); + } + + public AndCondition createAnd(Condition... conditions) { + return new AndCondition(this, conditions); + } + + public Condition createAnd(List conditions) { + return new AndCondition(this, conditions); + } + + public OrCondition createOr(Condition... conditions) { + return new OrCondition(this, conditions); + } + + public Condition createNot(Condition condition) { + return new NotCondition(this, condition); + } + + public Condition createIn(String propertyPath, Collection values) { + return new InCondition(this, propertyPath, values); + } + + public Condition createIn(String propertyPath, String subqueryText) { + return new InCondition(this, propertyPath, subqueryText); + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java index c77687988eb..5674a014de5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java @@ -16,11 +16,25 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; + +import java.util.Collection; + /** * @author mederly */ public class AndCondition extends JunctionCondition { - public AndCondition(Condition... conditions) { - super(conditions); + + public AndCondition(RootHibernateQuery rootHibernateQuery, Condition... conditions) { + super(rootHibernateQuery, conditions); + } + + public AndCondition(RootHibernateQuery rootHibernateQuery, Collection conditions) { + super(rootHibernateQuery, conditions); + } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + super.dumpToHql(sb, indent, "and"); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java index 6de053b0b2c..cd4e03636d7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/Condition.java @@ -16,27 +16,34 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import org.apache.commons.lang.Validate; +import org.hibernate.Query; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.MatchMode; import java.io.Serializable; import java.util.List; +import java.util.Set; /** * Condition in HQL. * * @author mederly */ -public class Condition { +public abstract class Condition { - public void dumpToHql(StringBuilder sb, int indent) { - if (indent >= 0) { - HibernateQuery.indent(sb, indent); - } - // TODO + protected RootHibernateQuery rootHibernateQuery; + + public Condition(RootHibernateQuery rootHibernateQuery) { + Validate.notNull(rootHibernateQuery, "rootHibernateQuery"); + this.rootHibernateQuery = rootHibernateQuery; } + public abstract void dumpToHql(StringBuilder sb, int indent); + public static void dumpToHql(StringBuilder sb, List conditions, int indent) { boolean first = true; for (Condition condition : conditions) { @@ -48,51 +55,4 @@ public static void dumpToHql(StringBuilder sb, List conditions, int i condition.dumpToHql(sb, indent); } } - - public static Condition gt(String propertyPath, Object value) { - //TODO - } - - public static Condition eq(String propertyPath, String value, Class type) { - return null; - } - - public static Condition and(List conditions) { - return null; - } - public static AndCondition and(Condition... conditions) { - return null; - } - - public static Condition isNull(String propertyName) { - return null; - } - - public static Condition eq(String propertyName, Object value) { - return null; - } - - public static Condition ge(String propertyName, Object value) { - return null; - } - - public static Condition lt(String propertyName, Object value) { - return null; - } - - public static Condition le(String propertyName, Object value) { - return null; - } - - public static Condition isNotNull(String propertyName) { - return null; - } - - public static Condition like(String propertyName, String value, MatchMode matchMode) { - return null; - } - - public void ignoreCase() { - - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java new file mode 100644 index 00000000000..b3fd1c85ecc --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class HibernateSubquery extends HibernateQuery { + + private HibernateQuery parentQuery; + + public HibernateSubquery(EntityDefinition primaryEntityDef, HibernateQuery parentQuery) { + super(primaryEntityDef); + Validate.notNull(parentQuery); + this.parentQuery = parentQuery; + } + + @Override + public RootHibernateQuery getRootQuery() { + return parentQuery.getRootQuery(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java index befda72202b..925ec83b916 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java @@ -16,6 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import org.apache.commons.lang.Validate; import org.hibernate.Query; import java.util.Collection; @@ -27,15 +30,29 @@ public class InCondition extends PropertyCondition { private Collection values; - private Query innerQuery; + private String innerQueryText; - public InCondition(String propertyPath, Query innerQuery) { - super(propertyPath); - this.innerQuery = innerQuery; + public InCondition(RootHibernateQuery rootHibernateQuery, String propertyPath, String innerQueryText) { + super(rootHibernateQuery, propertyPath); + Validate.notNull(innerQueryText); + this.innerQueryText = innerQueryText; } - public InCondition(String propertyPath, Collection values) { - super(propertyPath); + public InCondition(RootHibernateQuery rootHibernateQuery, String propertyPath, Collection values) { + super(rootHibernateQuery, propertyPath); + Validate.notNull(values); this.values = values; } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + if (values != null) { + String parameterNamePrefix = createParameterName(propertyPath); + String parameterName = rootHibernateQuery.addParameter(parameterNamePrefix, values); // TODO special treatment of collections? + sb.append(propertyPath).append(" in :").append(parameterName); + } else { + sb.append(propertyPath).append(" in (").append(innerQueryText).append(")"); + } + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java index 26a75ea5438..0301fc1d3f7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java @@ -16,12 +16,21 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; + /** * @author mederly */ public class IsNotNullCondition extends PropertyCondition { - public IsNotNullCondition(String propertyPath) { - super(propertyPath); + public IsNotNullCondition(RootHibernateQuery rootHibernateQuery, String propertyPath) { + super(rootHibernateQuery, propertyPath); + } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + sb.append(propertyPath).append(" is not null"); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java index 365ff7e4608..2f8ccf687f0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java @@ -16,11 +16,21 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; + /** * @author mederly */ public class IsNullCondition extends PropertyCondition { - public IsNullCondition(String propertyPath) { - super(propertyPath); + + public IsNullCondition(RootHibernateQuery rootHibernateQuery, String propertyPath) { + super(rootHibernateQuery, propertyPath); + } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + sb.append(propertyPath).append(" is null"); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java index 82ecb517f23..812c492a628 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java @@ -16,24 +16,57 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; + import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** * @author mederly */ -public class JunctionCondition extends Condition { +public abstract class JunctionCondition extends Condition { protected List components = new ArrayList<>(); - public JunctionCondition(Condition... conditions) { + public JunctionCondition(RootHibernateQuery rootHibernateQuery, Condition... conditions) { + super(rootHibernateQuery); for (Condition condition : conditions) { components.add(condition); } } + public JunctionCondition(RootHibernateQuery rootHibernateQuery, Collection conditions) { + super(rootHibernateQuery); + components.addAll(conditions); + } + public void add(Condition condition) { components.add(condition); } + public void dumpToHql(StringBuilder sb, int indent, String logicalOperation) { + if (components.isEmpty()) { + // probably some programming bug + throw new IllegalStateException("JunctionCondition with no components: " + this.getClass()); + } else if (components.size() == 1) { + components.get(0).dumpToHql(sb, indent); + } else { + HibernateQuery.indent(sb, indent); + sb.append("(\n"); + boolean first = true; + for (Condition component : components) { + if (first) { + first = false; + } else { + sb.append(" ").append(logicalOperation).append("\n"); + } + component.dumpToHql(sb, indent + 1); + } + sb.append("\n"); + HibernateQuery.indent(sb, indent); + sb.append(")"); + } + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java index bbf29aa2d8e..e76e4fa79f9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java @@ -16,6 +16,10 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import org.apache.commons.lang.Validate; + /** * @author mederly */ @@ -23,7 +27,16 @@ public class NotCondition extends Condition { protected Condition child; - public NotCondition(Condition child) { + public NotCondition(RootHibernateQuery rootHibernateQuery, Condition child) { + super(rootHibernateQuery); + Validate.notNull(child, "child"); this.child = child; } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + sb.append("not "); + child.dumpToHql(sb, -1); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java index 08a8f77b7e1..a80cda7b832 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java @@ -16,8 +16,20 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; + /** * @author mederly */ public class OrCondition extends JunctionCondition { + + public OrCondition(RootHibernateQuery rootHibernateQuery, Condition... conditions) { + super(rootHibernateQuery, conditions); + } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + super.dumpToHql(sb, indent, "or"); + } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java index 19b26fccd90..a1fd2d37d30 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java @@ -16,21 +16,38 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import org.apache.commons.lang.Validate; /** * @author mederly */ -public class PropertyCondition extends Condition { +public abstract class PropertyCondition extends Condition { protected String propertyPath; - public PropertyCondition(String propertyPath) { - Validate.notNull(propertyPath); + public PropertyCondition(RootHibernateQuery rootHibernateQuery, String propertyPath) { + super(rootHibernateQuery); + Validate.notNull(propertyPath, "propertyPath"); this.propertyPath = propertyPath; } public String getPropertyPath() { return propertyPath; } + + protected String createParameterName(String propertyPath) { + Validate.notEmpty(propertyPath, "propertyPath"); + int i = propertyPath.lastIndexOf('.'); + if (i < 0) { + return propertyPath; + } else { + String name = propertyPath.substring(i+1); + if (!name.isEmpty()) { + return name; + } else { + return "param"; // shouldn't occur + } + } + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java new file mode 100644 index 00000000000..71ef0ac39f0 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class SimpleComparisonCondition extends PropertyCondition { + + private Object value; + private String operator; + private boolean ignoreCase; + + public SimpleComparisonCondition(RootHibernateQuery rootHibernateQuery, String propertyPath, Object value, String operator, boolean ignoreCase) { + super(rootHibernateQuery, propertyPath); + Validate.notNull(value, "value"); + Validate.notNull(operator, "operator"); + this.value = value; + this.operator = operator; + this.ignoreCase = ignoreCase; + } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + + String finalPropertyPath; + Object finalPropertyValue; + if (ignoreCase) { + finalPropertyPath = "lower(" + propertyPath + ")"; + if (value instanceof String) { + finalPropertyValue = ((String) value).toLowerCase(); + } else { + throw new IllegalStateException("Non-string values cannot be compared with ignoreCase option: " + value); + } + } else { + finalPropertyPath = propertyPath; + finalPropertyValue = value; + } + + String parameterNamePrefix = createParameterName(propertyPath); + String parameterName = rootHibernateQuery.addParameter(parameterNamePrefix, finalPropertyValue); + sb.append(finalPropertyPath).append(" ").append(operator).append(" :").append(parameterName); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java index d5695bf5c8e..d065b239e07 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.query2.matcher; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; @@ -26,9 +27,9 @@ public class DefaultMatcher extends Matcher { @Override - public Condition match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) + public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, T value, String matcher) throws QueryException { - return basicMatch(operation, propertyName, value, false); + return basicMatch(null, operation, propertyName, value, false); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java index 9310cd97654..d9feb98c706 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java @@ -17,78 +17,87 @@ package com.evolveum.midpoint.repo.sql.query2.matcher; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.Validate; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.MatchMode; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.SimpleExpression; /** * @author lazyman */ public abstract class Matcher { + private static final Trace LOGGER = TraceManager.getTrace(Matcher.class); + /** * Create hibernate {@link Criterion} based on matcher defined in filter. * + * + * @param hibernateQuery * @param operation - * @param propertyName + * @param propertyPath * @param value * @param matcher Now type of {@link String}, but will be updated to {@link javax.xml.namespace.QName} * type after query-api update * @return * @throws QueryException */ - public abstract Condition match(ItemRestrictionOperation operation, String propertyName, T value, String matcher) + public abstract Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyPath, T value, String matcher) throws QueryException; - protected Condition basicMatch(ItemRestrictionOperation operation, String propertyName, Object value, + protected Condition basicMatch(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyPath, Object value, boolean ignoreCase) throws QueryException { + Validate.notNull(hibernateQuery, "hibernateQuery"); + + if (ignoreCase && !(value instanceof String)) { + LOGGER.warn("Ignoring ignoreCase setting for non-string value of {}", value); + ignoreCase = false; + } + Condition condition; switch (operation) { case EQ: if (value == null) { - condition = Condition.isNull(propertyName); + condition = hibernateQuery.createIsNull(propertyPath); } else { - condition = Condition.eq(propertyName, value); + condition = hibernateQuery.createEq(propertyPath, value, ignoreCase); } break; case GT: - condition = Condition.gt(propertyName, value); + condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, ">", ignoreCase); break; case GE: - condition = Condition.ge(propertyName, value); + condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, ">=", ignoreCase); break; case LT: - condition = Condition.lt(propertyName, value); + condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, "<", ignoreCase); break; case LE: - condition = Condition.le(propertyName, value); + condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, "<=", ignoreCase); break; case NOT_NULL: - condition = Condition.isNotNull(propertyName); + condition = hibernateQuery.createIsNotNull(propertyPath); break; case NULL: - condition = Condition.isNull(propertyName); + condition = hibernateQuery.createIsNull(propertyPath); break; case STARTS_WITH: - condition = Condition.like(propertyName, (String) value, MatchMode.START); + condition = hibernateQuery.createLike(propertyPath, (String) value, MatchMode.START, ignoreCase); break; case ENDS_WITH: - condition = Condition.like(propertyName, (String) value, MatchMode.END); + condition = hibernateQuery.createLike(propertyPath, (String) value, MatchMode.END, ignoreCase); break; case SUBSTRING: - condition = Condition.like(propertyName, (String) value, MatchMode.ANYWHERE); + condition = hibernateQuery.createLike(propertyPath, (String) value, MatchMode.ANYWHERE, ignoreCase); break; default: throw new QueryException("Unknown operation '" + operation + "'."); } - if (ignoreCase && (value instanceof String)) { - condition.ignoreCase(); - } - return condition; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java index 36a8d577fca..55f5af566fd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java @@ -22,13 +22,11 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; import org.apache.commons.lang.StringUtils; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; /** * @author lazyman @@ -45,7 +43,7 @@ public class PolyStringMatcher extends Matcher { public static final String NORM_IGNORE_CASE = "normIgnoreCase"; @Override - public Condition match(ItemRestrictionOperation operation, String propertyName, PolyString value, String matcher) + public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, PolyString value, String matcher) throws QueryException { boolean ignoreCase = STRICT_IGNORE_CASE.equals(matcher) @@ -54,10 +52,9 @@ public Condition match(ItemRestrictionOperation operation, String propertyName, if (StringUtils.isEmpty(matcher) || STRICT.equals(matcher) || STRICT_IGNORE_CASE.equals(matcher)) { - AndCondition conjunction = Condition.and( - createOrigMatch(operation, propertyName, value, ignoreCase), - createNormMatch(operation, propertyName, value, ignoreCase)); - + AndCondition conjunction = hibernateQuery.createAnd(); + conjunction.add(createOrigMatch(operation, propertyName, value, ignoreCase)); + conjunction.add(createNormMatch(operation, propertyName, value, ignoreCase)); return conjunction; } else if (ORIG.equals(matcher) || ORIG_IGNORE_CASE.equals(matcher)) { return createOrigMatch(operation, propertyName, value, ignoreCase); @@ -72,13 +69,13 @@ private Condition createNormMatch(ItemRestrictionOperation operation, String pro boolean ignoreCase) throws QueryException { String realValue = value != null ? value.getNorm() : null; - return basicMatch(operation, propertyName + '.' + RPolyString.F_NORM, realValue, ignoreCase); + return basicMatch(null, operation, propertyName + '.' + RPolyString.F_NORM, realValue, ignoreCase); } private Condition createOrigMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, boolean ignoreCase) throws QueryException { String realValue = value != null ? value.getOrig() : null; - return basicMatch(operation, propertyName + '.' + RPolyString.F_ORIG, realValue, ignoreCase); + return basicMatch(null, operation, propertyName + '.' + RPolyString.F_ORIG, realValue, ignoreCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java index 3f9e9a84858..5279cd03eb7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; @@ -30,11 +31,11 @@ public class StringMatcher extends Matcher { public static final String IGNORE_CASE = StringIgnoreCaseMatchingRule.NAME.getLocalPart(); @Override - public Condition match(ItemRestrictionOperation operation, String propertyName, String value, String matcher) + public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, String value, String matcher) throws QueryException { boolean ignoreCase = IGNORE_CASE.equalsIgnoreCase(matcher); - return basicMatch(operation, propertyName, value, ignoreCase); + return basicMatch(null, operation, propertyName, value, ignoreCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java index e4cc0c6a9b1..c46151a1365 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java @@ -33,7 +33,7 @@ public class AndRestriction extends NaryLogicalRestriction { @Override public Condition interpret() throws QueryException { validateFilter(); - AndCondition conjunction = new AndCondition(); + AndCondition conjunction = getContext().getHibernateQuery().createAnd(); updateJunction(filter.getConditions(), conjunction); return conjunction; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java index 9a65b3617eb..81656e1e65c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java @@ -31,7 +31,7 @@ public class InOidRestriction extends Restriction { @Override public Condition interpret() throws QueryException { - return new InCondition(context.getCurrentHqlPropertyPath() + ".oid", filter.getOids()); + return getContext().getHibernateQuery().createIn(context.getCurrentHqlPropertyPath() + ".oid", filter.getOids()); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index 7151dc42575..6eabed7ab6c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -44,6 +44,7 @@ import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; @@ -56,6 +57,7 @@ import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; @@ -171,8 +173,8 @@ private String prepareJoins(ItemPath relativePath) throws QueryException { return currentHqlPath; } - protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) { - HibernateQuery hibernateQuery = context.getHibernateQuery(); + protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) throws QueryException { + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) String joinedItemJpaName = joinedItemDefinition.getJpaName(); String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; @@ -183,11 +185,12 @@ protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) List conditions = new ArrayList<>(vcd.getAdditionalParams().length); for (VirtualQueryParam vqp : vcd.getAdditionalParams()) { // e.g. name = "assignmentOwner", type = RAssignmentOwner.class, value = "ABSTRACT_ROLE" - Condition c = Condition.eq(joinedItemAlias + "." + vqp.name(), vqp.value(), vqp.type()); + Object value = createQueryParamValue(vqp); + Condition c = hibernateQuery.createEq(joinedItemAlias + "." + vqp.name(), value); conditions.add(c); } if (conditions.size() > 1) { - condition = Condition.and(conditions); + condition = hibernateQuery.createAnd(conditions); } else if (conditions.size() == 1) { condition = conditions.iterator().next(); } @@ -196,16 +199,43 @@ protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) return joinedItemAlias; } + /** + * This method provides transformation from {@link String} value defined in + * {@link com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam#value()} to real object. Currently only + * to simple types and enum values. + */ + private Object createQueryParamValue(VirtualQueryParam param) throws QueryException { + Class type = param.type(); + String value = param.value(); + + try { + if (type.isPrimitive()) { + return type.getMethod("valueOf", new Class[]{String.class}).invoke(null, new Object[]{value}); + } + + if (type.isEnum()) { + return Enum.valueOf(type, value); + } + } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException|RuntimeException ex) { + throw new QueryException("Couldn't transform virtual query parameter '" + + param.name() + "' from String to '" + type + "', reason: " + ex.getMessage(), ex); + } + + throw new QueryException("Couldn't transform virtual query parameter '" + + param.name() + "' from String to '" + type + "', it's not yet implemented."); + } + + protected String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { - HibernateQuery hibernateQuery = context.getHibernateQuery(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) String joinedItemJpaName = anyAssociationName; String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); - Condition condition = Condition.and( - Condition.eq(joinedItemAlias + ".ownerType", ownerType), - Condition.eq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); + Condition condition = hibernateQuery.createAnd( + hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType), + hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); return joinedItemAlias; @@ -245,7 +275,7 @@ protected Condition createCondition(String propertyName, Object value, ValueFilt matchingRule = filter.getMatchingRule().getLocalPart(); } - return matcher.match(operation, propertyName, value, matchingRule); + return matcher.match(null, operation, propertyName, value, matchingRule); } protected Object getValue(List values) { @@ -339,9 +369,10 @@ protected Condition addIsNotNullIfNecessary(Condition condition, String property if (!isNegated()) { return condition; } - AndCondition conjunction = new AndCondition(); + RootHibernateQuery hibernateQuery = getContext().getHibernateQuery(); + AndCondition conjunction = hibernateQuery.createAnd(); conjunction.add(condition); - conjunction.add(new IsNotNullCondition(propertyPath)); + conjunction.add(hibernateQuery.createIsNotNull(propertyPath)); return conjunction; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java index 43729b1342c..a6b120bb964 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java @@ -33,6 +33,6 @@ public class NotRestriction extends UnaryLogicalRestriction { public Condition interpret() throws QueryException { validateFilter(); Condition condition = interpretChildFilter(); - return new NotCondition(condition); + return getContext().getHibernateQuery().createNot(condition); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java index 4600fb20c71..84bbf908659 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java @@ -32,7 +32,7 @@ public class OrRestriction extends NaryLogicalRestriction { @Override public Condition interpret() throws QueryException { validateFilter(); - OrCondition disjunction = new OrCondition(); + OrCondition disjunction = getContext().getHibernateQuery().createOr(); updateJunction(filter.getConditions(), disjunction); return disjunction; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java index 48bd5ca34f6..d3f8383e538 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -22,10 +22,15 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.hqm.QueryParameterValue; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; import org.hibernate.Query; +import java.util.HashMap; +import java.util.Map; + /** * @author lazyman */ @@ -33,10 +38,11 @@ public class OrgRestriction extends Restriction { @Override public Condition interpret() throws QueryException { + RootHibernateQuery hibernateQuery = getContext().getHibernateQuery(); if (filter.isRoot()) { // oid in (select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1) - return new InCondition(context.getCurrentHqlPropertyPath() + ".oid", - getSession().createQuery("select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1")); + return hibernateQuery.createIn(context.getCurrentHqlPropertyPath() + ".oid", + "select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1"); } if (filter.getOrgRef() == null) { @@ -47,6 +53,7 @@ public Condition interpret() throws QueryException { throw new QueryException("No oid specified in organization reference " + filter.getOrgRef().debugDump()); } + String orgOidParamName = hibernateQuery.addParameter("orgOid", filter.getOrgRef().getOid()); String oidQueryText; // oid in ... switch (filter.getScope()) { case ONE_LEVEL: @@ -55,7 +62,7 @@ public Condition interpret() throws QueryException { "from RObjectReference ref " + "where " + "ref.referenceType = " + nameOf(RReferenceOwner.OBJECT_PARENT_ORG) + " and " + - "ref.targetOid = :orgOid"; + "ref.targetOid = :" + orgOidParamName; break; case SUBTREE: default: @@ -65,11 +72,8 @@ public Condition interpret() throws QueryException { "where " + "ref.referenceType = " + nameOf(RReferenceOwner.OBJECT_PARENT_ORG) + " and " + "ref.targetOid in (" + - "select descendantOid from ROrgClosure where ancestorOid = :orgOid"; + "select descendantOid from ROrgClosure where ancestorOid = :" + orgOidParamName; } - Query oidQuery = getSession().createQuery(oidQueryText); - oidQuery.setParameter("orgOid", filter.getOrgRef().getOid()); - return new InCondition(context.getCurrentHqlPropertyPath() + ".oid", oidQuery); + return hibernateQuery.createIn(context.getCurrentHqlPropertyPath() + ".oid", oidQueryText); } - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index 0ed955e51f4..e52f09e8965 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -20,27 +20,18 @@ import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext.ProperDefinitionSearchResult; +import com.evolveum.midpoint.repo.sql.query2.ProperDefinitionSearchResult; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; -import org.apache.commons.lang.StringUtils; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; import javax.xml.namespace.QName; import java.util.List; @@ -68,6 +59,7 @@ public Condition interpretInternal(String hqlPath) throws QueryException { } InterpretationContext context = getContext(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); ItemPath fullPath = getFullPath(filter.getPath()); ProperDefinitionSearchResult defResult = context.findProperDefinition(fullPath, Definition.class); if (defResult == null || defResult.getItemDefinition() == null) { @@ -85,22 +77,22 @@ public Condition interpretInternal(String hqlPath) throws QueryException { refValueRelation = refValue.getRelation(); refValueTargetType = refValue.getTargetType(); } - AndCondition conjunction = Condition.and(); - conjunction.add(handleEqOrNull(propertyFullNamePrefix + ObjectReference.F_TARGET_OID, refValueOid)); + AndCondition conjunction = hibernateQuery.createAnd(); + conjunction.add(handleEqOrNull(hibernateQuery, propertyFullNamePrefix + ObjectReference.F_TARGET_OID, refValueOid)); if (refValueOid != null) { if (refValueRelation == null) { // Return only references without relation - conjunction.add(Condition.eq(propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); + conjunction.add(hibernateQuery.createEq(propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); } else if (refValueRelation.equals(PrismConstants.Q_ANY)) { // Return all relations => no restriction } else { // return references with specific relation - conjunction.add(handleEqOrNull(propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); + conjunction.add(handleEqOrNull(hibernateQuery, propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); } if (refValueTargetType != null) { - conjunction.add(handleEqOrNull(propertyFullNamePrefix + ObjectReference.F_TYPE, + conjunction.add(handleEqOrNull(hibernateQuery, propertyFullNamePrefix + ObjectReference.F_TYPE, ClassMapper.getHQLTypeForQName(refValueTargetType))); } } @@ -111,11 +103,11 @@ public Condition interpretInternal(String hqlPath) throws QueryException { } - private Condition handleEqOrNull(String propertyName, Object value) { + private Condition handleEqOrNull(RootHibernateQuery hibernateQuery, String propertyName, Object value) { if (value == null) { - return Condition.isNull(propertyName); + return hibernateQuery.createIsNull(propertyName); } else { - return Condition.eq(propertyName, value); + return hibernateQuery.createEq(propertyName, value); } } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java index 87b09d21646..70f46eb5183 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -16,21 +16,15 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.EqualsCondition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; import javax.xml.namespace.QName; import java.util.Arrays; @@ -44,26 +38,28 @@ public class TypeRestriction extends Restriction { @Override public Condition interpret() throws QueryException { - String property = getContext().getCurrentHqlPropertyPath() + "." + RObject.F_OBJECT_TYPE_CLASS; + InterpretationContext context = getContext(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + + String property = context.getCurrentHqlPropertyPath() + "." + RObject.F_OBJECT_TYPE_CLASS; Set values = getValues(filter.getType()); Condition basedOnType; if (values.size() > 1) { - basedOnType = new InCondition(property, values); + basedOnType = hibernateQuery.createIn(property, values); } else { - basedOnType = new EqualsCondition(property, values.iterator().next()); + basedOnType = hibernateQuery.createEq(property, values.iterator().next()); } if (filter.getFilter() == null) { return basedOnType; } - InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); Condition basedOnFilter = interpreter.interpretFilter(filter.getFilter(), context, this); - return new AndCondition(basedOnType, basedOnFilter); + return hibernateQuery.createAnd(basedOnType, basedOnFilter); } private Set getValues(QName typeQName) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ClassMapper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ClassMapper.java index 6bfd7088971..ae0f4367618 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ClassMapper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ClassMapper.java @@ -103,6 +103,18 @@ public static RObjectType getHQLTypeForQName(QName qname) { throw new IllegalArgumentException("Couldn't find hql type for qname " + qname); } + public static Class getHqlClassForHqlName(String hqlName) { + if (hqlName == null) { + return null; + } + for (RObjectType entry : types.values()) { + if (entry.getClazz().getSimpleName().equals(hqlName)) { + return entry.getClazz(); + } + } + throw new IllegalArgumentException("Couldn't find hql type for hql name " + hqlName); + } + public static ObjectTypes getObjectTypeForHQLType(RObjectType type) { if (type == null) { return null; From 9dfb7acc9e246d56caadd81a4955fd2da0f29e05 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sun, 22 Nov 2015 01:03:44 +0100 Subject: [PATCH 012/116] HQL-based query interpreter passes repo-sql-impl-test. (No new features yet, however.) --- .../midpoint/prism/query/ObjectQuery.java | 11 + .../midpoint/repo/sql/BaseSQLRepoTest.java | 5 + .../repo/sql/QueryInterpreter2Test.java | 2185 +++++++++++++++++ ...count-by-attribute-and-extension-value.xml | 35 + .../query/query-account-by-attribute.xml | 27 + .../repo-sql-impl-test/testng-integration.xml | 2 +- .../repo/sql/SqlRepositoryServiceImpl.java | 32 +- .../repo/sql/data/common/RObject.java | 36 +- .../repo/sql/data/common/RShadow.java | 4 + .../sql/query/definition/QueryEntity.java | 2 + .../definition/VirtualAny.java} | 5 +- .../repo/sql/query2/QueryInterpreter2.java | 24 +- .../definition/ClassDefinitionParser.java | 14 + .../sql/query2/definition/Definition.java | 33 +- .../query2/definition/EntityDefinition.java | 18 - .../repo/sql/query2/definition/JaxbName.java | 39 - .../repo/sql/query2/definition/JaxbType.java | 35 - .../query2/definition/JpaDefinitionPath.java | 31 +- .../sql/query2/definition/QueryEntity.java | 42 - ...ryParam.java => VirtualAnyDefinition.java} | 20 +- .../query2/definition/VirtualCollection.java | 42 - .../VirtualCollectionDefinition.java | 2 + .../sql/query2/definition/VirtualEntity.java | 41 - .../definition/VirtualEntityDefinition.java | 2 + .../query2/definition/VirtualProperty.java | 41 - .../definition/VirtualPropertyDefinition.java | 2 + .../query2/definition/VirtualReference.java | 41 - .../repo/sql/query2/hqm/HibernateQuery.java | 2 +- .../sql/query2/hqm/JoinSpecification.java | 2 +- .../sql/query2/hqm/QueryParameterValue.java | 18 + .../sql/query2/hqm/RootHibernateQuery.java | 22 +- .../sql/query2/matcher/DefaultMatcher.java | 2 +- .../sql/query2/matcher/PolyStringMatcher.java | 16 +- .../sql/query2/matcher/StringMatcher.java | 2 +- .../restriction/AnyPropertyRestriction.java | 18 +- .../restriction/CollectionRestriction.java | 7 +- .../query2/restriction/ItemRestriction.java | 40 +- .../query2/restriction/OrgRestriction.java | 2 +- .../restriction/ReferenceRestriction.java | 18 +- 39 files changed, 2541 insertions(+), 379 deletions(-) create mode 100644 repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java create mode 100644 repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute-and-extension-value.xml create mode 100644 repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute.xml rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/{query2/definition/Any.java => query/definition/VirtualAny.java} (90%) delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{VirtualQueryParam.java => VirtualAnyDefinition.java} (62%) delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java index 65ea65894ae..b7202f569eb 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java @@ -33,6 +33,8 @@ public class ObjectQuery implements DebugDumpable, Serializable { private ObjectPaging paging; private boolean allowPartialResults = false; + private boolean useNewQueryInterpreter = true; + public ObjectFilter getFilter() { return filter; } @@ -57,6 +59,14 @@ public void setAllowPartialResults(boolean allowPartialResults) { this.allowPartialResults = allowPartialResults; } + public boolean isUseNewQueryInterpreter() { + return useNewQueryInterpreter; + } + + public void setUseNewQueryInterpreter(boolean useNewQueryInterpreter) { + this.useNewQueryInterpreter = useNewQueryInterpreter; + } + public static ObjectQuery createObjectQuery(ObjectFilter filter) { ObjectQuery query = new ObjectQuery(); query.setFilter(filter); @@ -106,6 +116,7 @@ public ObjectQuery cloneEmpty() { if (this.allowPartialResults) { clone.allowPartialResults = true; } + clone.useNewQueryInterpreter = this.useNewQueryInterpreter; return clone; } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/BaseSQLRepoTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/BaseSQLRepoTest.java index 84ef9fcc68e..1b81b8f35ee 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/BaseSQLRepoTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/BaseSQLRepoTest.java @@ -40,6 +40,7 @@ import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; import org.hibernate.Criteria; +import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.dialect.H2Dialect; @@ -196,6 +197,10 @@ protected String getInterpretedQuery(Session session, Cla return HibernateToSqlTranslator.toSql(factory, ((RQueryImpl) rQuery).getQuery().getQueryString()); } + protected String hqlToSql(String hql) { + return HibernateToSqlTranslator.toSql(factory, hql); + } + protected String getInterpretedQuery(Session session, Class type, File file) throws Exception { return getInterpretedQuery(session, type, file, false); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java new file mode 100644 index 00000000000..ed942b4afce --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -0,0 +1,2185 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql; + +import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule; +import com.evolveum.midpoint.prism.match.PolyStringOrigMatchingRule; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.EqualFilter; +import com.evolveum.midpoint.prism.query.GreaterFilter; +import com.evolveum.midpoint.prism.query.InOidFilter; +import com.evolveum.midpoint.prism.query.LessFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.query.OrgFilter; +import com.evolveum.midpoint.prism.query.RefFilter; +import com.evolveum.midpoint.prism.query.SubstringFilter; +import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.schema.SchemaRegistry; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.repo.sql.data.common.RConnector; +import com.evolveum.midpoint.repo.sql.data.common.RGenericObject; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.RObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.ROrg; +import com.evolveum.midpoint.repo.sql.data.common.ROrgClosure; +import com.evolveum.midpoint.repo.sql.data.common.RReportOutput; +import com.evolveum.midpoint.repo.sql.data.common.RRole; +import com.evolveum.midpoint.repo.sql.data.common.RShadow; +import com.evolveum.midpoint.repo.sql.data.common.RTask; +import com.evolveum.midpoint.repo.sql.data.common.RUser; +import com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus; +import com.evolveum.midpoint.repo.sql.data.common.enums.RTaskExecutionStatus; +import com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query.RQuery; +import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; +import com.evolveum.midpoint.repo.sql.query2.RQueryImpl; +import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; +import com.evolveum.midpoint.repo.sql.util.HibernateToSqlTranslator; +import com.evolveum.midpoint.schema.MidPointPrismContextFactory; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.GenericObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportOutputType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Disjunction; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.ProjectionList; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Property; +import org.hibernate.criterion.Restrictions; +import org.hibernate.criterion.Subqueries; +import org.hibernate.sql.JoinType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; +import java.io.File; +import java.io.IOException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * @author lazyman + */ +@ContextConfiguration(locations = {"../../../../../ctx-test.xml"}) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +public class QueryInterpreter2Test extends BaseSQLRepoTest { + + private static final Trace LOGGER = TraceManager.getTrace(QueryInterpreter2Test.class); + private static final File TEST_DIR = new File("./src/test/resources/query"); + + private static final QName SKIP_AUTOGENERATION = new QName("http://example.com/p", "skipAutogeneration"); + + @BeforeSuite + public void setup() throws SchemaException, SAXException, IOException { + PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); + PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); + } + + @BeforeClass + public void beforeClass() throws Exception { + super.beforeClass(); + + PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); + + List> objects = prismContext.parseObjects( + new File(FOLDER_BASIC, "objects.xml")); + OperationResult result = new OperationResult("add objects"); + for (PrismObject object : objects) { + repositoryService.addObject(object, null, result); + } + + result.recomputeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + } + + @Test(enabled = false) + public void test001QueryNameNorm() throws Exception { + Session session = open(); + + try { + /* + * ### user: Equal (name, "asdf", PolyStringNorm) + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " u.name.norm = :norm"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test002QueryNameOrig() throws Exception { + Session session = open(); + + try { + /* + * ### user: Equal (name, "asdf", PolyStringOrig) + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " u.name.orig = :orig"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test003QueryNameStrict() throws Exception { + Session session = open(); + + try { + /* + * ### user: Equal (name, "asdf", PolyStringOrig) + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + null, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " ( u.name.orig = :orig and u.name.norm = :norm )"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test010QueryOrganizationNorm() throws Exception { + Session session = open(); + + try { + /* + * ### user: Equal (organization, "asdf", PolyStringNorm) + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, + PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.organization o\n" + + "where\n" + + " o.norm = :norm"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + private void assertEqualsIgnoreWhitespace(String expected, String real) { + LOGGER.info("exp. query>\n{}\nreal query>\n{}", expected, real); + String expNorm = StringUtils.normalizeSpace(expected); + String realNorm = StringUtils.normalizeSpace(real); + if (!expNorm.equals(realNorm)) { + String m = "Generated query is not correct. Expected:\n" + expected + "\nActual:\n" + real + "\n\nNormalized versions:\n\n" + + "Expected: " + expNorm + "\nActual: " + realNorm + "\n"; + LOGGER.error("{}", m); + throw new AssertionError(m); + } + } + + @Test(enabled = false) + public void test011QueryOrganizationOrig() throws Exception { + Session session = open(); + try { + /* + * ### user: Equal (organization, "asdf", PolyStringOrig) + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, + PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.organization o\n" + + "where\n" + + " o.orig = :orig"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test012QueryOrganizationStrict() throws Exception { + Session session = open(); + try { + /* + * ### user: Equal (organization, "asdf") + */ + + ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, + null, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.organization o\n" + + "where\n" + + " ( o.orig = :orig and o.norm = :norm )"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test020QueryTwoOrganizationsNormAnd() throws Exception { + Session session = open(); + try { + /* + * UserType: And (Equal (organization, 'asdf', PolyStringNorm), + * Equal (organization, 'ghjk', PolyStringNorm)) + */ + ObjectFilter filter = AndFilter.createAnd( + EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")), + EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringNormMatchingRule.NAME, new PolyString("ghjk", "ghjk"))); + + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.organization o\n" + + " left join u.organization o2\n" + + "where\n" + + " ( o.norm = :norm and o2.norm = :norm2 )"; + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test021QueryTwoOrganizationsStrictOr() throws Exception { + Session session = open(); + try { + /* + * UserType: Or (Equal (organization, 'asdf'), + * Equal (organization, 'ghjk')) + */ + ObjectFilter filter = OrFilter.createOr( + EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, null, new PolyString("asdf", "asdf")), + EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, null, new PolyString("ghjk", "ghjk"))); + + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.organization o\n" + + " left join u.organization o2\n" + + "where\n" + + " ( ( o.orig = :orig and o.norm = :norm ) or\n" + + " ( o2.orig = :orig2 and o2.norm = :norm2 ) )"; + + // NOTE: this could be implemented more efficiently by using only one join... or the query itself can be formulated + // via In filter (when available) or ForValue filter (also, when available) + + String real = getInterpretedQuery(session, UserType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test025QueryOrganizationOrigPolymorphic() throws Exception { + Session session = open(); + try { + /* + * ### object: Equal (organization, "asdf", PolyStringOrig) + */ + ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, + PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " o.fullObject, o.stringsCount, o.longsCount, o.datesCount, o.referencesCount, o.polysCount, o.booleansCount\n" + + "from\n" + + " RObject o\n" + + " left join o.organization o2\n" + + "where\n" + + " o2.orig = :orig"; + + String real = getInterpretedQuery(session, ObjectType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test030QueryTaskDependent() throws Exception { + Session session = open(); + + try { + /* + * ### task: Equal (dependent, "123456") + */ + ObjectFilter filter = EqualFilter.createEqual(TaskType.F_DEPENDENT, TaskType.class, prismContext, null, "123456"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String expected = "select\n" + + " t.fullObject, t.stringsCount, t.longsCount, t.datesCount, t.referencesCount, t.polysCount, t.booleansCount\n" + + "from\n" + + " RTask t\n" + + " left join t.dependent d\n" + + "where\n" + + " d = :d"; + + String real = getInterpretedQuery(session, TaskType.class, query); + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false, expectedExceptions = QueryException.class) + public void test040QueryClob() throws Exception { + Session session = open(); + + try { + ObjectFilter filter = EqualFilter.createEqual(UserType.F_DESCRIPTION, UserType.class, prismContext, null, "aaa"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + //should throw exception, because description is lob and can't be queried + getInterpretedQuery(session, UserType.class, query); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test050QueryEnum() throws Exception { + Session session = open(); + try { + /* + * ### task: Equal (executionStatus, WAITING) + */ + ObjectFilter filter = EqualFilter.createEqual(TaskType.F_EXECUTION_STATUS, TaskType.class, prismContext, + null, TaskExecutionStatusType.WAITING); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, TaskType.class, query); + + String expected = "select\n" + + " t.fullObject,\n" + + " t.stringsCount,\n" + + " t.longsCount,\n" + + " t.datesCount,\n" + + " t.referencesCount,\n" + + " t.polysCount,\n" + + " t.booleansCount\n" + + "from\n" + + " RTask t\n" + + "where\n" + + " t.executionStatus = :executionStatus\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test060QueryEnabled() throws Exception { + Session session = open(); + try { + /* + * ### task: Equal (activation/administrativeStatus, ENABLED) + * ==> from RUser u where u.activation.administrativeStatus = com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus.ENABLED + */ + + String real = getInterpretedQuery(session, UserType.class, + new File(TEST_DIR, "query-user-by-enabled.xml")); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " u.activation.administrativeStatus = :administrativeStatus\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test070QueryGenericLong() throws Exception { + Session session = open(); + try { + /* + * ### generic: And (Equal (name, "generic object", PolyStringNorm), + * Equal (c:extension/p:intType, 123)) + * ==> from RGenericObject g + * left join g.longs l (l.ownerType = com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType.EXTENSION and l.name = 'http://example.com/p#intType') + * where + * g.name.norm = 'generic object' and + * l.value = 123 + */ + + String real = getInterpretedQuery(session, GenericObjectType.class, + new File(TEST_DIR, "query-and-generic.xml")); + + String expected = "select\n" + + " g.fullObject, g.stringsCount, g.longsCount, g.datesCount, g.referencesCount, g.polysCount, g.booleansCount\n" + + "from\n" + + " RGenericObject g\n" + + " left join g.longs l with (l.ownerType = :ownerType and l.name = :name)\n" + + "where\n" + + " ( g.name.norm = :norm and l.value = :value )\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void test072QueryAccountByAttribute() throws Exception { + Session session = open(); + try { + String real = getInterpretedQuery(session, ShadowType.class, + new File(TEST_DIR, "query-account-by-attribute.xml")); + String expected = "select\n" + + " s.fullObject, s.stringsCount, s.longsCount, s.datesCount, s.referencesCount, s.polysCount, s.booleansCount\n" + + "from\n" + + " RShadow s\n" + + " left join s.strings s2 with ( s2.ownerType = :ownerType and s2.name = :name )\n" + + "where\n" + + " s2.value = :value\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test074QueryAccountByAttributeAndExtensionValue() throws Exception { + Session session = open(); + try { + String real = getInterpretedQuery(session, ShadowType.class, + new File(TEST_DIR, "query-account-by-attribute-and-extension-value.xml")); + String expected = "select\n" + + " s.fullObject, s.stringsCount, s.longsCount, s.datesCount, s.referencesCount, s.polysCount, s.booleansCount\n" + + "from\n" + + " RShadow s\n" + + " left join s.strings s2 with ( s2.ownerType = :ownerType and s2.name = :name )\n" + + " left join s.longs l with ( l.ownerType = :ownerType2 and l.name = :name2 )\n" + + "where\n" + + " (\n" + + " s2.value = :value and\n" + + " l.value = :value2\n" + + " )"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test076QueryOrComposite() throws Exception { + Session session = open(); + try { + /* + * ### shadow: + * Or ( + * Equal (intent, "some account type"), + * Equal (attributes/f:foo, "foo value"), + * Equal (extension/p:stringType, "uid=test,dc=example,dc=com"), + * Ref (resourceRef, d0db5be9-cb93-401f-b6c1-86ffffe4cd5e)) + * + * ==> from RShadow r left join r.strings s1 where + * r.intent = 'some account type' or + * (s1.ownerType = RObjectExtensionType.ATTRIBUTES and s1.name = 'http://midpoint.evolveum.com/blabla#foo' and s1.value = 'foo value') or + * (s1.ownerType = RObjectExtensionType.EXTENSION and s1.name = 'http://example.com/p#stringType' and s1.value = 'uid=test,dc=example,dc=com') or + * (r.resourceRef.targetOid = 'd0db5be9-cb93-401f-b6c1-86ffffe4cd5e' and r.resourceRef.relation = '#' and r.resourceRef.type = '...#ResourceType') + * + * [If we used AND instead of OR, this SHOULD BE left join r.strings s1, left join r.strings s2] + */ + String real = getInterpretedQuery(session, ShadowType.class, + new File(TEST_DIR, "query-or-composite.xml")); + + String expected = "select\n" + + " s.fullObject, s.stringsCount, s.longsCount, s.datesCount, s.referencesCount, s.polysCount, s.booleansCount\n" + + "from\n" + + " RShadow s\n" + + " left join s.strings s2 with ( s2.ownerType = :ownerType and s2.name = :name )\n" + + " left join s.strings s3 with ( s3.ownerType = :ownerType2 and s3.name = :name2 )\n" + + "where\n" + + " (\n" + + " s.intent = :intent or\n" + + " s2.value = :value or\n" + + " s3.value = :value2 or\n" + + " (\n" + + " s.resourceRef.targetOid = :targetOid and\n" + + " s.resourceRef.relation = :relation and\n" + + " s.resourceRef.type = :type\n" + + " )\n" + + " )\n"; + + /* + ownerType = ATTRIBUTES (com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType.ATTRIBUTES) + name = http://midpoint.evolveum.com/blabla#foo + value = foo value + ownerType2 = com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType.EXTENSION + name2 = http://example.com/p#stringType + value2 = uid=test,dc=example,dc=com + intent = some account type + targetOid = d0db5be9-cb93-401f-b6c1-86ffffe4cd5e + relation = # + type = com.evolveum.midpoint.repo.sql.data.common.other.RObjectType.RESOURCE + */ + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test100QueryObjectByName() throws Exception { + Session session = open(); + + try { + /* + * ### object: Equal (name, "cpt. Jack Sparrow") + * Order by name, ASC + * + * ==> from RObject o where name.orig = 'cpt. Jack Sparrow' and name.norm = 'cpt jack sparrow' + * order by name.orig asc + */ + EqualFilter filter = EqualFilter.createEqual(ObjectType.F_NAME, ObjectType.class, prismContext, + null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); + + String real = getInterpretedQuery(session, ObjectType.class, query); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " (\n" + + " o.name.orig = :orig and\n" + + " o.name.norm = :norm\n" + + " )\n" + + "order by o.name.orig asc\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test110QueryUserByFullName() throws Exception { + Session session = open(); + + try { + String real = getInterpretedQuery(session, UserType.class, + new File(TEST_DIR, "query-user-by-fullName.xml")); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " u.fullName.norm = :norm\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test112QueryUserSubstringFullName() throws Exception { + Session session = open(); + + try { + String real = getInterpretedQuery(session, UserType.class, + new File(TEST_DIR, "query-user-substring-fullName.xml")); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " lower(u.fullName.norm) like :norm"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test114QueryUserByName() throws Exception { + Session session = open(); + + try { + String real = getInterpretedQuery(session, UserType.class, + new File(TEST_DIR, "query-user-by-name.xml")); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " u.name.norm = :norm"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test120QueryConnectorByType() throws Exception { + Session session = open(); + + try { + String real = getInterpretedQuery(session, ConnectorType.class, + new File(TEST_DIR, "query-connector-by-type.xml")); + String expected = "select\n" + + " c.fullObject,\n" + + " c.stringsCount,\n" + + " c.longsCount,\n" + + " c.datesCount,\n" + + " c.referencesCount,\n" + + " c.polysCount,\n" + + " c.booleansCount\n" + + "from\n" + + " RConnector c\n" + + "where\n" + + " c.connectorType = :connectorType\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test130QueryAccountByAttributesAndResourceRef() throws Exception { + Session session = open(); + try { + String real = getInterpretedQuery(session, ShadowType.class, + new File(TEST_DIR, "query-account-by-attributes-and-resource-ref.xml")); + String expected = "select\n" + + " s.fullObject,\n" + + " s.stringsCount,\n" + + " s.longsCount,\n" + + " s.datesCount,\n" + + " s.referencesCount,\n" + + " s.polysCount,\n" + + " s.booleansCount\n" + + "from\n" + + " RShadow s\n" + + " left join s.strings s2 with ( s2.ownerType = :ownerType and s2.name = :name )\n" + + "where\n" + + " (\n" + + " (\n" + + " s.resourceRef.targetOid = :targetOid and\n" + + " s.resourceRef.relation = :relation and\n" + + " s.resourceRef.type = :type\n" + + " ) and\n" + + " s2.value = :value\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test140QueryUserAccountRef() throws Exception { + Session session = open(); + try { + /* + * ### user: Ref (linkRef, 123) + * + * ==> select from RUser u left join u.linkRef l where + * l.targetOid = '123' and l.relation = '#' + */ + RefFilter filter = RefFilter.createReferenceEqual(UserType.F_LINK_REF, UserType.class, prismContext, "123"); + String real = getInterpretedQuery(session, UserType.class, ObjectQuery.createObjectQuery(filter)); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.linkRef l\n" + + "where\n" + + " (\n" + + " l.targetOid = :targetOid and\n" + + " l.relation = :relation\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test150QueryUserAssignmentTargetRef() throws Exception { + Session session = open(); + try { + /* + * ### user: Ref (assignment/targetRef, '123', RoleType) + * + * ==> select from RUser u left join u.assignments a where + * a.assignmentOwner = RAssignmentOwner.FOCUS and + * a.targetRef.targetOid = '123' and + * a.targetRef.relation = '#' and + * a.targetRef.type = RObjectType.ROLE + */ + ObjectReferenceType ort = new ObjectReferenceType(); + ort.setOid("123"); + ort.setType(RoleType.COMPLEX_TYPE); + RefFilter filter = RefFilter.createReferenceEqual( + new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_TARGET_REF), + UserType.class, prismContext, ort.asReferenceValue()); + String real = getInterpretedQuery(session, UserType.class, ObjectQuery.createObjectQuery(filter)); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "where\n" + + " (\n" + + " a.targetRef.targetOid = :targetOid and\n" + + " a.targetRef.relation = :relation and\n" + + " a.targetRef.type = :type\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + + @Test + public void test160QueryTrigger() throws Exception { + final Date NOW = new Date(); + + Session session = open(); + try { + XMLGregorianCalendar thisScanTimestamp = XmlTypeConverter.createXMLGregorianCalendar(NOW.getTime()); + + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(ObjectType.class); + ItemPath triggerPath = new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP); + ObjectFilter filter = LessFilter.createLess(triggerPath, objectDef, thisScanTimestamp, true); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, ObjectType.class, query); + + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + " left join o.trigger t\n" + + "where\n" + + " t.timestamp <= :timestamp\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test170QueryAssignmentActivationAdministrativeStatus() throws Exception { + Session session = open(); + try { + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(UserType.class); + ItemPath activationPath = new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); + ObjectFilter filter = EqualFilter.createEqual(activationPath, objectDef, ActivationStatusType.ENABLED); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, UserType.class, query); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "where\n" + + " a.activation.administrativeStatus = :administrativeStatus\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test180QueryInducementActivationAdministrativeStatus() throws Exception { + Session session = open(); + try { + /* + * ### role: Equal (inducement/activation/administrativeStatus, ENABLED) + * + * ==> select from RRole r left join r.assignments a where + * a.assignmentOwner = RAssignmentOwner.ABSTRACT_ROLE and <--- this differentiates inducements from assignments + * a.activation.administrativeStatus = RActivationStatus.ENABLED + */ + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(RoleType.class); + ItemPath activationPath = new ItemPath(RoleType.F_INDUCEMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); + ObjectFilter filter = EqualFilter.createEqual(activationPath, objectDef, ActivationStatusType.ENABLED); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, RoleType.class, query); + + String expected = "select\n" + + " r.fullObject,\n" + + " r.stringsCount,\n" + + " r.longsCount,\n" + + " r.datesCount,\n" + + " r.referencesCount,\n" + + " r.polysCount,\n" + + " r.booleansCount\n" + + "from\n" + + " RRole r\n" + + " left join r.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "where\n" + + " a.activation.administrativeStatus = :administrativeStatus\n"; + + // assignmentOwner = com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner.ABSTRACT_ROLE + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test182QueryInducementAndAssignmentActivationAdministrativeStatus() throws Exception { + Session session = open(); + try { + /* + * ### Role: Or (Equal (assignment/activation/administrativeStatus, RActivationStatus.ENABLED), + * Equal (inducement/activation/administrativeStatus, RActivationStatus.ENABLED)) + */ + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(RoleType.class); + + //filter1 + ItemPath activationPath1 = new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); + ObjectFilter filter1 = EqualFilter.createEqual(activationPath1, objectDef, ActivationStatusType.ENABLED); + + //filter2 + ItemPath activationPath2 = new ItemPath(RoleType.F_INDUCEMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); + ObjectFilter filter2 = EqualFilter.createEqual(activationPath2, objectDef, ActivationStatusType.ENABLED); + + ObjectQuery query = ObjectQuery.createObjectQuery(OrFilter.createOr(filter1, filter2)); + String real = getInterpretedQuery(session, RoleType.class, query); + + String expected = "select\n" + + " r.fullObject,\n" + + " r.stringsCount,\n" + + " r.longsCount,\n" + + " r.datesCount,\n" + + " r.referencesCount,\n" + + " r.polysCount,\n" + + " r.booleansCount\n" + + "from\n" + + " RRole r\n" + + " left join r.assignments a with a.assignmentOwner = :assignmentOwner\n" + + " left join r.assignments a2 with a2.assignmentOwner = :assignmentOwner2\n" + + "where\n" + + " (\n" + + " a.activation.administrativeStatus = :administrativeStatus or\n" + + " a2.activation.administrativeStatus = :administrativeStatus2\n" + + " )\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test190QueryUserByActivationDouble() throws Exception { + Date NOW = new Date(); + + Session session = open(); + try { + /* + * ### user: And (Equal (activation/administrativeStatus, RActivationStatus.ENABLED), + * Equal (activation/validFrom, '...')) + * + * ==> select u from RUser u where u.activation.administrativeStatus = RActivationStatus.ENABLED and + * u.activation.validFrom = ... + */ + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(UserType.class); + ObjectFilter filter1 = EqualFilter.createEqual(new ItemPath(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), objectDef, + ActivationStatusType.ENABLED); + ObjectFilter filter2 = EqualFilter.createEqual(new ItemPath(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM), objectDef, + XmlTypeConverter.createXMLGregorianCalendar(NOW.getTime())); + + ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(filter1, filter2)); + String real = getInterpretedQuery(session, UserType.class, query); + + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " (\n" + + " u.activation.administrativeStatus = :administrativeStatus and\n" + + " u.activation.validFrom = :validFrom\n" + + " )\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test200QueryTriggerTimestampDoubleWrong() throws Exception { + final Date NOW = new Date(); + + Session session = open(); + try { + XMLGregorianCalendar thisScanTimestamp = XmlTypeConverter.createXMLGregorianCalendar(NOW.getTime()); + + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(ObjectType.class); + ItemPath triggerPath = new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP); + ObjectFilter greater = GreaterFilter.createGreater(triggerPath, objectDef, thisScanTimestamp, false); + ObjectFilter lesser = LessFilter.createLess(triggerPath, objectDef, thisScanTimestamp, false); + AndFilter and = AndFilter.createAnd(greater, lesser); + LOGGER.info(and.debugDump()); + + ObjectQuery query = ObjectQuery.createObjectQuery(and); + String real = getInterpretedQuery(session, ObjectType.class, query); + + // correct translation but the filter is wrong: we need to point to THE SAME timestamp -> i.e. ForValue should be used here + String expected = "select\n" + + " o.fullObject, o.stringsCount, o.longsCount, o.datesCount, o.referencesCount, o.polysCount, o.booleansCount\n" + + "from\n" + + " RObject o\n" + + " left join o.trigger t\n" + + " left join o.trigger t2\n" + + "where\n" + + " (\n" + + " t.timestamp > :timestamp and\n" + + " t2.timestamp < :timestamp2\n" + + " )\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + private void addFullObjectProjectionList(String prefix, ProjectionList list, boolean group) { + if (prefix == null) { + prefix = ""; + } else { + prefix = prefix + "."; + } + + if (group) { + list.add(Projections.groupProperty(prefix + "fullObject")); + list.add(Projections.groupProperty(prefix + "stringsCount")); + list.add(Projections.groupProperty(prefix + "longsCount")); + list.add(Projections.groupProperty(prefix + "datesCount")); + list.add(Projections.groupProperty(prefix + "referencesCount")); + list.add(Projections.groupProperty(prefix + "polysCount")); + list.add(Projections.groupProperty(prefix + "booleansCount")); + } else { + list.add(Projections.property(prefix + "fullObject")); + list.add(Projections.property(prefix + "stringsCount")); + list.add(Projections.property(prefix + "longsCount")); + list.add(Projections.property(prefix + "datesCount")); + list.add(Projections.property(prefix + "referencesCount")); + list.add(Projections.property(prefix + "polysCount")); + list.add(Projections.property(prefix + "booleansCount")); + } + } + + @Test + public void test300CountObjectOrderByName() throws Exception { + Session session = open(); + + try { + EqualFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); + + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); + + String real = getInterpretedQuery(session, UserType.class, query, true); + String expected = "select\n" + + " count(*)\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " (\n" + + " u.name.orig = :orig and\n" + + " u.name.norm = :norm\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test310CountObjectOrderByNameWithoutFilter() throws Exception { + Session session = open(); + + try { + ObjectPaging paging = ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING); + ObjectQuery query = ObjectQuery.createObjectQuery(null, paging); + + String real = getInterpretedQuery(session, ObjectType.class, query, true); + String expected = "select\n" + + " count(*)\n" + + "from\n" + + " RObject o\n"; // ordering does not make sense here + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + /** + * Q{AND: (EQUALS: parent, PPV(null)),PAGING: O: 0,M: 5,BY: name, D:ASCENDING, + * + * @throws Exception + */ + @Test + public void test320CountTaskOrderByName() throws Exception { + Session session = open(); + + try { + EqualFilter filter = EqualFilter.createEqual(TaskType.F_PARENT, TaskType.class, prismContext, null); + + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + query.setPaging(ObjectPaging.createPaging(null, null, TaskType.F_NAME, OrderDirection.ASCENDING)); + + String real = getInterpretedQuery(session, TaskType.class, query, true); + String expected = "select\n" + + " count(*)\n" + + "from\n" + + " RTask t\n" + + "where\n" + + " t.parent is null"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test330InOidTest() throws Exception { + Session session = open(); + try { + InOidFilter filter = InOidFilter.createInOid(Arrays.asList("1", "2")); + + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, ObjectType.class, query, false); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " o.oid in :oid\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test340QueryOrgTreeFindOrgs() throws Exception { + Session session = open(); + + try { + + OrgFilter orgFilter = OrgFilter.createOrg("some oid", OrgFilter.Scope.ONE_LEVEL); + ObjectQuery objectQuery = ObjectQuery.createObjectQuery(orgFilter); + objectQuery.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); + objectQuery.setUseNewQueryInterpreter(true); + + String real = getInterpretedQuery(session, OrgType.class, objectQuery); + + OperationResult result = new OperationResult("query org structure"); + repositoryService.searchObjects(OrgType.class, objectQuery, null, result); + + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " ROrg o\n" + + "where\n" + + " o.oid in (select ref.ownerOid from RObjectReference ref where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and ref.targetOid = :orgOid)\n" + + "order by o.name.orig asc\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(enabled = false) + public void asdf() throws Exception { + Session session = open(); + try { + Criteria main = session.createCriteria(RUser.class, "u"); + Criteria a = main.createCriteria("assignments", "a"); + a.add(Restrictions.eq("a.assignmentOwner", RAssignmentOwner.FOCUS)); + Criteria e = a.createCriteria("a.extension"); + + Criteria s = e.createCriteria("strings", "s"); + + Conjunction c2 = Restrictions.conjunction(); + c2.add(Restrictions.eq("s.extensionType", RAssignmentExtensionType.EXTENSION)); + c2.add(Restrictions.eq("s.name", new QName("http://midpoint.evolveum.com/blabla", "foo"))); + c2.add(Restrictions.eq("s.value", "uid=jbond,ou=People,dc=example,dc=com")); + + Conjunction c1 = Restrictions.conjunction(); + c1.add(Restrictions.eq("a.targetRef.targetOid", "1234")); + c1.add(Restrictions.eq("a.targetRef.type", RObjectType.ORG)); + + main.add(Restrictions.and(c1, c2)); + + main.setProjection(Projections.property("u.fullObject")); + + String expected = HibernateToSqlTranslator.toSql(main); + LOGGER.info(">>> >>> {}", expected); + } finally { + close(session); + } + } + + @Test + public void test400ActivationQueryWrong() throws Exception { + PrismObjectDefinition focusObjectDef = prismContext.getSchemaRegistry() + .findObjectDefinitionByCompileTimeClass(UserType.class); + + XMLGregorianCalendar thisScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); + + OrFilter filter = OrFilter.createOr( + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, + thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, + thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + focusObjectDef, thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + focusObjectDef, thisScanTimestamp, true) + ); + + Session session = open(); + try { + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, UserType.class, query, false); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + " left join u.assignments a2 with a2.assignmentOwner = :assignmentOwner2\n" + + "where\n" + + " (\n" + + " u.activation.validFrom <= :validFrom or\n" + + " u.activation.validTo <= :validTo or\n" + + " a.activation.validFrom <= :validFrom2 or\n" + + " a2.activation.validTo <= :validTo2\n" + + " )\n"; + + // correct translation but probably not what the requester wants (use ForValue instead) + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test410ActivationQueryWrong() throws Exception { + PrismObjectDefinition focusObjectDef = prismContext.getSchemaRegistry() + .findObjectDefinitionByCompileTimeClass(UserType.class); + + XMLGregorianCalendar lastScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); + XMLGregorianCalendar thisScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); + + OrFilter filter = OrFilter.createOr( + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, + lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, + thisScanTimestamp, true) + ), + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, + lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, + thisScanTimestamp, true) + ), + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + focusObjectDef, lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + focusObjectDef, thisScanTimestamp, true) + ), + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + focusObjectDef, lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + focusObjectDef, thisScanTimestamp, true) + ) + ); + + Session session = open(); + try { + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, UserType.class, query, false); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + " left join u.assignments a2 with a2.assignmentOwner = :assignmentOwner2\n" + + " left join u.assignments a3 with a3.assignmentOwner = :assignmentOwner3\n" + + " left join u.assignments a4 with a4.assignmentOwner = :assignmentOwner4\n" + + "where\n" + + " (\n" + + " (\n" + + " u.activation.validFrom > :validFrom and\n" + + " u.activation.validFrom <= :validFrom2\n" + + " ) or\n" + + " (\n" + + " u.activation.validTo > :validTo and\n" + + " u.activation.validTo <= :validTo2\n" + + " ) or\n" + + " (\n" + + " a.activation.validFrom > :validFrom3 and\n" + + " a2.activation.validFrom <= :validFrom4\n" + + " ) or\n" + + " (\n" + + " a3.activation.validTo > :validTo3 and\n" + + " a4.activation.validTo <= :validTo4\n" + + " )\n" + + " )\n"; + + // TODO rewrite with ForValue + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test500OrgQuery() throws Exception { + File objects = new File("src/test/resources/orgstruct/org-monkey-island.xml"); + OperationResult opResult = new OperationResult("test500OrgQuery"); + List> orgStruct = prismContext.parseObjects(objects); + + for (PrismObject o : orgStruct) { + repositoryService.addObject((PrismObject) o, null, opResult); + } + opResult.computeStatusIfUnknown(); + AssertJUnit.assertTrue(opResult.isSuccess()); + + checkQueryResult(ObjectType.class, "00000000-8888-6666-0000-100000000001", OrgFilter.Scope.ONE_LEVEL, 4); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-100000000001", OrgFilter.Scope.ONE_LEVEL, 1); + checkQueryResult(OrgType.class, "00000000-8888-6666-0000-100000000001", OrgFilter.Scope.ONE_LEVEL, 3); + checkQueryResult(OrgType.class, "00000000-8888-6666-0000-100000000001", OrgFilter.Scope.SUBTREE, 5); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-100000000001", OrgFilter.Scope.SUBTREE, 6); + checkQueryResult(ObjectType.class, "00000000-8888-6666-0000-100000000001", OrgFilter.Scope.SUBTREE, 11); + checkQueryResult(ObjectType.class, "00000000-8888-6666-0000-100000000006", OrgFilter.Scope.ONE_LEVEL, 4); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-100000000006", OrgFilter.Scope.ONE_LEVEL, 4); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-100000000006", OrgFilter.Scope.SUBTREE, 4); + checkQueryResult(OrgType.class, "00000000-8888-6666-0000-100000000006", OrgFilter.Scope.ONE_LEVEL, 0); + checkQueryResult(OrgType.class, "00000000-8888-6666-0000-100000000006", OrgFilter.Scope.SUBTREE, 0); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-200000000002", OrgFilter.Scope.ONE_LEVEL, 2); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-200000000002", OrgFilter.Scope.SUBTREE, 2); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-200000000001", OrgFilter.Scope.ONE_LEVEL, 1); + checkQueryResult(UserType.class, "00000000-8888-6666-0000-200000000001", OrgFilter.Scope.SUBTREE, 1); + } + + private void checkQueryResult(Class type, String oid, OrgFilter.Scope scope, int count) + throws Exception { + LOGGER.info("checkQueryResult"); + + OrgFilter orgFilter = OrgFilter.createOrg(oid, scope); + ObjectQuery query = ObjectQuery.createObjectQuery(orgFilter); + query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); + query.setUseNewQueryInterpreter(true); + + OperationResult result = new OperationResult("checkQueryResult"); + List> objects = repositoryService.searchObjects(type, query, null, result); + for (PrismObject object : objects) { + LOGGER.info("{}", object.getOid()); + } + int realCount = objects.size(); + AssertJUnit.assertEquals("Expected count doesn't match for searchObjects " + orgFilter, count, realCount); + + result.computeStatusIfUnknown(); + AssertJUnit.assertTrue(result.isSuccess()); + + realCount = repositoryService.countObjects(type, query, result); + AssertJUnit.assertEquals("Expected count doesn't match for countObjects " + orgFilter, count, realCount); + + result.computeStatusIfUnknown(); + AssertJUnit.assertTrue(result.isSuccess()); + } + + @Test + public void test510QueryNameAndOrg() throws Exception { + Session session = open(); + + try { + EqualFilter eqFilter = EqualFilter.createEqual(ObjectType.F_NAME, ObjectType.class, prismContext, + null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); + + OrgFilter orgFilter = OrgFilter.createOrg("12341234-1234-1234-1234-123412341234"); + + ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(eqFilter, orgFilter)); + query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); + + String real = getInterpretedQuery(session, UserType.class, query); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " (\n" + + " (\n" + + " u.name.orig = :orig and\n" + + " u.name.norm = :norm\n" + + " ) and\n" + + " u.oid in (select ref.ownerOid from RObjectReference ref " + + " where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and " + + " ref.targetOid in (select descendantOid from ROrgClosure where ancestorOid = :orgOid))\n" + + " )\n" + + "order by u.name.orig asc\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + +// @Test +// public void test520QueryEmployeeTypeAndOrgType() throws Exception { +// Session session = open(); +// +// try { +// EqualFilter nameFilter = EqualFilter.createEqual(ObjectType.F_NAME, ObjectType.class, prismContext, +// null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); +// +// EqualFilter numberFilter = EqualFilter.createEqual(UserType.F_EMPLOYEE_NUMBER, UserType.class, prismContext, +// null, "123"); +// +// EqualsFilter orgTypeFilter = EqualsFilter.createEqual(OrgType.F_ORG_TYPE, OrgType.class, prismContext, +// null, "orgtypevalue"); +// +// ObjectQuery query = ObjectQuery.createObjectQuery(OrFilter.createOr( +// AndFilter.createAnd(nameFilter, numberFilter)//, +//// orgTypeFilter +// )); +// query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); +// +// String real = getInterpretedQuery(session, ObjectType.class, query); +// +// LOGGER.info("real query>\n{}", new Object[]{real}); +// } finally { +// close(session); +// } +// } + + @Test + public void test530queryUserSubstringName() throws Exception { + Session session = open(); + + try { + SubstringFilter substring = SubstringFilter.createSubstring(ObjectType.F_NAME, ObjectType.class, + prismContext, PolyStringOrigMatchingRule.NAME, "a"); + substring.setAnchorStart(true); + ObjectQuery objectQuery = ObjectQuery.createObjectQuery(substring); + objectQuery.setUseNewQueryInterpreter(true); + + String real = getInterpretedQuery(session, ObjectType.class, objectQuery); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " o.name.orig like :orig\n"; + assertEqualsIgnoreWhitespace(expected, real); + + OperationResult result = new OperationResult("test530queryUserSubstringName"); + int count = repositoryService.countObjects(ObjectType.class, objectQuery, result); + AssertJUnit.assertEquals(2, count); + + substring = SubstringFilter.createSubstring(ObjectType.F_NAME, ObjectType.class, + prismContext, PolyStringOrigMatchingRule.NAME, "a"); + objectQuery = ObjectQuery.createObjectQuery(substring); + objectQuery.setUseNewQueryInterpreter(true); + count = repositoryService.countObjects(ObjectType.class, objectQuery, result); + AssertJUnit.assertEquals(18, count); + + } finally { + close(session); + } + } + + @Test + public void test540queryObjectClassTypeUser() throws Exception { + Session session = open(); + + try { + TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, null); + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " o.objectTypeClass = :objectTypeClass\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test550queryObjectClassTypeAbstractRole() throws Exception { + Session session = open(); + + try { + TypeFilter type = TypeFilter.createType(AbstractRoleType.COMPLEX_TYPE, null); + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " o.objectTypeClass in :objectTypeClass"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test560queryMetadataTimestamp() throws Exception { + Session session = open(); + + try { + XMLGregorianCalendar timeXml = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); + + LessFilter less = LessFilter.createLess( + new ItemPath(ReportOutputType.F_METADATA, MetadataType.F_CREATE_TIMESTAMP), + ReportOutputType.class, prismContext, timeXml, true); + + String real = getInterpretedQuery(session, ReportOutputType.class, ObjectQuery.createObjectQuery(less)); + String expected = "select\n" + + " r.fullObject,\n" + + " r.stringsCount,\n" + + " r.longsCount,\n" + + " r.datesCount,\n" + + " r.referencesCount,\n" + + " r.polysCount,\n" + + " r.booleansCount\n" + + "from\n" + + " RReportOutput r\n" + + "where\n" + + " r.createTimestamp <= :createTimestamp"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test570queryObjectypeByTypeUserAndLocality() throws Exception { + Session session = open(); + try { +// Criteria main = session.createCriteria(RObject.class, "o"); +// ProjectionList projections = Projections.projectionList(); +// addFullObjectProjectionList("o", projections, false); +// main.setProjection(projections); +// +// Conjunction c = Restrictions.conjunction(); +// main.add(c); +// c.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.USER)); +// c.add(Restrictions.and(Restrictions.eq("o.localityUser.orig", "Caribbean"), +// Restrictions.eq("o.localityUser.norm", "caribbean"))); +// +// String expected = HibernateToSqlTranslator.toSql(main); + + EqualFilter eq = EqualFilter.createEqual(new ItemPath(UserType.F_LOCALITY), UserType.class, prismContext, + new PolyString("Caribbean", "caribbean")); + TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, eq); + + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + // TODO - why not RUser here? we unnecessarily join all of RObject subtypes... + "where\n" + + " (\n" + + " o.objectTypeClass = :objectTypeClass and\n" + + " (\n" + + " o.localityUser.orig = :orig and\n" + + " o.localityUser.norm = :norm\n" + + " )\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + checkQueryTypeAlias(hqlToSql(real), "m_user", "locality_orig", "locality_norm"); + } finally { + close(session); + } + } + + /** + * This checks aliases, if they were generated correctly for query. Alias for table as "table" parameter + * must be used for columns in "properties" parameter. + * + * @param query + * @param table + * @param properties + */ + private void checkQueryTypeAlias(String query, String table, String... properties) { + LOGGER.info("SQL generated = {}", query); + + String[] array = query.split(" "); + String alias = null; + for (int i = 0; i < array.length; i++) { + if (table.equals(array[i])) { + alias = array[i + 1]; + break; + } + } + AssertJUnit.assertNotNull(alias); + + for (String property : properties) { + for (String token : array) { + if (token.endsWith(property + "=?") && !token.startsWith(alias + ".")) { + AssertJUnit.fail("Property '" + property + "' doesn't have proper alias '" + + alias + "' in token '" + token + "'"); + } + } + } + } + + @Test + public void test575QueryObjectypeByTypeOrgAndLocality() throws Exception { + Session session = open(); + try { + EqualFilter eq = EqualFilter.createEqual(new ItemPath(OrgType.F_LOCALITY), OrgType.class, prismContext, + new PolyString("Caribbean", "caribbean")); + TypeFilter type = TypeFilter.createType(OrgType.COMPLEX_TYPE, eq); + + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " (\n" + + " o.objectTypeClass = :objectTypeClass and\n" + + " (\n" + + " o.locality.orig = :orig and\n" + + " o.locality.norm = :norm\n" + + " )\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + checkQueryTypeAlias(hqlToSql(real), "m_org", "locality_orig", "locality_norm"); + } finally { + close(session); + } + } + + @Test + public void test580QueryObjectypeByTypeAndExtensionAttribute() throws Exception { + Session session = open(); + try { + EqualFilter eq = EqualFilter.createEqual( + new ItemPath(ObjectType.F_EXTENSION, new QName("http://example.com/p", "weapon")), + UserType.class, prismContext, "some weapon name"); + TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, eq); + + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + " left join o.strings s with ( s.ownerType = :ownerType and s.name = :name )\n" + + "where\n" + + " (\n" + + " o.objectTypeClass = :objectTypeClass and\n" + + " s.value = :value\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + + } finally { + close(session); + } + } + + @Test + public void test590QueryObjectypeByTypeAndReference() throws Exception { + Session session = open(); + try { + RefFilter ref = RefFilter.createReferenceEqual(UserType.F_LINK_REF, UserType.class, prismContext, "123"); + TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, ref); + + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + " left join o.linkRef l\n" + + "where\n" + + " (\n" + + " o.objectTypeClass = :objectTypeClass and\n" + + " (\n" + + " l.targetOid = :targetOid and\n" + + " l.relation = :relation\n" + + " )\n" + + " )\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test600QueryObjectypeByTypeComplex() throws Exception { + Session session = open(); + try { +// Criteria main = session.createCriteria(RObject.class, "o"); +// ProjectionList projections = Projections.projectionList(); +// addFullObjectProjectionList("o", projections, false); +// main.setProjection(projections); +// +// Conjunction c1 = Restrictions.conjunction(); +// c1.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.USER)); +// Criterion e1 = Restrictions.and(Restrictions.eq("o.localityUser.orig", "Caribbean"), +// Restrictions.eq("o.localityUser.norm", "caribbean")); +// Criterion e2 = Restrictions.and(Restrictions.eq("o.localityUser.orig", "Adriatic"), +// Restrictions.eq("o.localityUser.norm", "adriatic")); +// c1.add(Restrictions.or(e1, e2)); +// +// Conjunction c2 = Restrictions.conjunction(); +// c2.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.ORG)); +// Criteria o1 = main.createCriteria("o.orgType", "o1", JoinType.LEFT_OUTER_JOIN); +// c2.add(Restrictions.eq("o1.elements", "functional")); +// +// Criterion c3 = Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.REPORT); +// +// main.add(Restrictions.or(c1, c2, c3)); +// String expected = HibernateToSqlTranslator.toSql(main); + + + EqualFilter eq1 = EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, prismContext, + new PolyString("Caribbean", "caribbean")); + EqualFilter eq2 = EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, prismContext, + new PolyString("Adriatic", "adriatic")); + TypeFilter type1 = TypeFilter.createType(UserType.COMPLEX_TYPE, OrFilter.createOr(eq1, eq2)); + + EqualFilter equal = EqualFilter.createEqual(OrgType.F_ORG_TYPE, OrgType.class, prismContext, "functional"); + TypeFilter type2 = TypeFilter.createType(OrgType.COMPLEX_TYPE, equal); + + TypeFilter type3 = TypeFilter.createType(ReportType.COMPLEX_TYPE, null); + + OrFilter or = OrFilter.createOr(type1, type2, type3); + + String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(or)); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + " left join o.orgType o2\n" + + "where\n" + + " (\n" + + " (\n" + + " o.objectTypeClass = :objectTypeClass and\n" + + " (\n" + + " (\n" + + " o.localityUser.orig = :orig and\n" + + " o.localityUser.norm = :norm\n" + + " ) or\n" + + " (\n" + + " o.localityUser.orig = :orig2 and\n" + + " o.localityUser.norm = :norm2\n" + + " )\n" + + " )\n" + + " ) or\n" + + " (\n" + + " o.objectTypeClass = :objectTypeClass2 and\n" + + " o2 = :o2\n" + + " ) or\n" + + " o.objectTypeClass = :objectTypeClass3\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test(expectedExceptions = QueryException.class) + public void test610QueryGenericClob() throws Exception { + Session session = open(); + try { + EqualFilter eq = EqualFilter.createEqual( + new ItemPath(ObjectType.F_EXTENSION, new QName("http://example.com/p", "locations")), + GenericObjectType.class, prismContext, null); + + getInterpretedQuery(session, GenericObjectType.class, ObjectQuery.createObjectQuery(eq)); + } catch (QueryException ex) { + LOGGER.info("Exception", ex); + throw ex; + } finally { + close(session); + } + } + + @Test + public void test620QueryGenericString() throws Exception { + Session session = open(); + try { + EqualFilter eq = EqualFilter.createEqual( + new ItemPath(ObjectType.F_EXTENSION, new QName("http://example.com/p", "stringType")), + GenericObjectType.class, prismContext, "asdf"); + + String real = getInterpretedQuery(session, GenericObjectType.class, ObjectQuery.createObjectQuery(eq)); + String expected = "select\n" + + " g.fullObject,\n" + + " g.stringsCount,\n" + + " g.longsCount,\n" + + " g.datesCount,\n" + + " g.referencesCount,\n" + + " g.polysCount,\n" + + " g.booleansCount\n" + + "from\n" + + " RGenericObject g\n" + + " left join g.strings s with ( s.ownerType = :ownerType and s.name = :name )\n" + + "where\n" + + " s.value = :value\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + +// @Test(enabled = false) +// public void atest100() throws Exception { +// Session session = open(); +// +// try { +// String expected = null;//HibernateToSqlTranslator.toSql(main); +// +// List secondaryEquals = new ArrayList<>(); +// EqualFilter eq = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, SchemaConstantsGenerated.ICF_S_UID), +// new PrismPropertyDefinition(SchemaConstantsGenerated.ICF_S_UID, DOMUtil.XSD_STRING, prismContext), +// "8daaeeae-f0c7-41c9-b258-2a3351aa8876"); +// secondaryEquals.add(eq); +// eq = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, SchemaConstantsGenerated.ICF_S_NAME), +// new PrismPropertyDefinition(SchemaConstantsGenerated.ICF_S_NAME, DOMUtil.XSD_STRING, prismContext), +// "some-name"); +// secondaryEquals.add(eq); +// +// OrFilter secondaryIdentifierFilter = OrFilter.createOr((List) secondaryEquals); +// RefFilter ref = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, +// prismContext, "ef2bc95b-76e0-48e2-86d6-3d4f02d3e1a2"); +// +// AndFilter filter = AndFilter.createAnd(ref, secondaryIdentifierFilter); +// ObjectQuery query = ObjectQuery.createObjectQuery(filter); +// LOGGER.debug("Query\n{}", query); +// +// QueryEngine engine = new QueryEngine(repositoryService.getConfiguration(), prismContext); +// RQuery rQuery = engine.interpret(query, ShadowType.class, null, false, session); +// RQueryCriteriaImpl rci = (RQueryCriteriaImpl) rQuery; +// System.out.println(rci); +// System.out.println(rci.getCriteria()); +// //just test if DB will handle it or throws some exception +// List l = rQuery.list(); +// LOGGER.info(">>>>>>>>asdfasdfasdfasdf{}",l.size()); +// +// String real = getInterpretedQuery(session, ShadowType.class, query); +// +// LOGGER.info("exp. query>\n{}\nreal query>\n{}", new Object[]{expected, real}); +// AssertJUnit.assertEquals(expected, real); +// } finally { +// close(session); +// } +// } + + @Test + public void test630QueryGenericBoolean() throws Exception { + Session session = open(); + try { + EqualFilter eq = EqualFilter.createEqual( + new ItemPath(ObjectType.F_EXTENSION, SKIP_AUTOGENERATION), + GenericObjectType.class, prismContext, true); + + ObjectQuery objectQuery = ObjectQuery.createObjectQuery(eq); + objectQuery.setUseNewQueryInterpreter(true); + + String real = getInterpretedQuery(session, GenericObjectType.class, objectQuery); + String expected = "select\n" + + " g.fullObject,\n" + + " g.stringsCount,\n" + + " g.longsCount,\n" + + " g.datesCount,\n" + + " g.referencesCount,\n" + + " g.polysCount,\n" + + " g.booleansCount\n" + + "from\n" + + " RGenericObject g\n" + + " left join g.booleans b with ( b.ownerType = :ownerType and b.name = :name )\n" + + "where\n" + + " b.value = :value\n"; + + assertEqualsIgnoreWhitespace(expected, real); + + OperationResult result = new OperationResult("search"); + List> objects = repositoryService.searchObjects(GenericObjectType.class, + objectQuery, null, result); + result.computeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + + AssertJUnit.assertNotNull(objects); + AssertJUnit.assertEquals(1, objects.size()); + + PrismObject obj = objects.get(0); + AssertJUnit.assertTrue(obj.getCompileTimeClass().equals(GenericObjectType.class)); + + result = new OperationResult("count"); + long count = repositoryService.countObjects(GenericObjectType.class, objectQuery, + result); + result.computeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + AssertJUnit.assertEquals(1, count); + } finally { + close(session); + } + } + + @Test + public void test640queryAssignmentExtensionBoolean() throws Exception { + Session session = open(); + try { + SchemaRegistry registry = prismContext.getSchemaRegistry(); + PrismObjectDefinition userDef = registry.findObjectDefinitionByCompileTimeClass(UserType.class); + PrismContainerDefinition assignmentDef = userDef.findContainerDefinition(UserType.F_ASSIGNMENT); + PrismPropertyDefinition propDef = assignmentDef.createPropertyDefinition(SKIP_AUTOGENERATION, DOMUtil.XSD_BOOLEAN); + + EqualFilter eq = EqualFilter.createEqual( + new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_EXTENSION, SKIP_AUTOGENERATION), + propDef, null, true); + + ObjectQuery objectQuery = ObjectQuery.createObjectQuery(eq); + objectQuery.setUseNewQueryInterpreter(true); + + String real = getInterpretedQuery(session, UserType.class, objectQuery); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + " left join a.extension e\n" + + " left join e.booleans b with b.name = :name\n" + + "where\n" + + " b.value = :value"; + assertEqualsIgnoreWhitespace(expected, real); + + OperationResult result = new OperationResult("search"); + List> objects = repositoryService.searchObjects(UserType.class, + objectQuery, null, result); + result.computeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + + AssertJUnit.assertNotNull(objects); + AssertJUnit.assertEquals(1, objects.size()); + + PrismObject obj = objects.get(0); + AssertJUnit.assertTrue(obj.getCompileTimeClass().equals(UserType.class)); + + result = new OperationResult("count"); + long count = repositoryService.countObjects(UserType.class, objectQuery, result); + result.computeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + AssertJUnit.assertEquals(1, count); + } finally { + close(session); + } + } + + protected String getInterpretedQuery(Session session, Class type, ObjectQuery query, + boolean interpretCount) throws Exception { + + LOGGER.info("QUERY TYPE TO CONVERT :\n{}", (query.getFilter() != null ? query.getFilter().debugDump(3) : null)); + + QueryEngine2 engine = new QueryEngine2(repositoryService.getConfiguration(), prismContext); + RQuery rQuery = engine.interpret(query, type, null, interpretCount, session); + //just test if DB will handle it or throws some exception + if (interpretCount) { + rQuery.uniqueResult(); + } else { + rQuery.list(); + } + + return ((RQueryImpl) rQuery).getQuery().getQueryString(); + } +} diff --git a/repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute-and-extension-value.xml b/repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute-and-extension-value.xml new file mode 100644 index 00000000000..bd45bd7010b --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute-and-extension-value.xml @@ -0,0 +1,35 @@ + + + + + + + + + c:attributes/a1 + abcdef + + + c:extension/m:shoeSize + 42 + + + + diff --git a/repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute.xml b/repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute.xml new file mode 100644 index 00000000000..7dbc51d5c08 --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/resources/query/query-account-by-attribute.xml @@ -0,0 +1,27 @@ + + + + + + + c:attributes/s:foo + uid=jbond,ou=People,dc=example,dc=com + + + diff --git a/repo/repo-sql-impl-test/testng-integration.xml b/repo/repo-sql-impl-test/testng-integration.xml index 6d8f2d8d591..e2cd0129f47 100644 --- a/repo/repo-sql-impl-test/testng-integration.xml +++ b/repo/repo-sql-impl-test/testng-integration.xml @@ -26,7 +26,7 @@ - + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index cf8033fe845..eb8c45db3f2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -43,6 +43,7 @@ import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; +import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; @@ -1002,8 +1003,14 @@ private int countObjectsAttempt(Class type, ObjectQuer SQLQuery sqlQuery = session.createSQLQuery("SELECT COUNT(*) FROM " + RUtil.getTableName(hqlType)); longCount = (Number) sqlQuery.uniqueResult(); } else { - QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); - RQuery rQuery = engine.interpret(query, type, null, true, session); + RQuery rQuery; + if (query.isUseNewQueryInterpreter()) { + QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); + rQuery = engine.interpret(query, type, null, true, session); + } else { + QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); + rQuery = engine.interpret(query, type, null, true, session); + } longCount = (Number) rQuery.uniqueResult(); } @@ -1146,8 +1153,15 @@ private SearchResultList> searchObjectsAtt Session session = null; try { session = beginReadOnlyTransaction(); - QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); - RQuery rQuery = engine.interpret(query, type, options, false, session); + RQuery rQuery; + + if (query.isUseNewQueryInterpreter()) { + QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); + rQuery = engine.interpret(query, type, options, false, session); + } else { + QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); + rQuery = engine.interpret(query, type, options, false, session); + } List objects = rQuery.list(); LOGGER.trace("Found {} objects, translating to JAXB.", new Object[]{(objects != null ? objects.size() : 0)}); @@ -2160,8 +2174,14 @@ private void searchObjectsIterativeAttempt(Class type, Session session = null; try { session = beginReadOnlyTransaction(); - QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); - RQuery rQuery = engine.interpret(query, type, options, false, session); + RQuery rQuery; + if (query.isUseNewQueryInterpreter()) { + QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); + rQuery = engine.interpret(query, type, options, false, session); + } else { + QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); + rQuery = engine.interpret(query, type, options, false, session); + } ScrollableResults results = rQuery.scroll(ScrollMode.FORWARD_ONLY); try { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 75d71aaae23..3263d1d458a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -19,7 +19,15 @@ import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.repo.sql.data.common.any.*; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyConverter; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtBoolean; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtDate; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtLong; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtPolyString; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtReference; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtString; +import com.evolveum.midpoint.repo.sql.data.common.any.ROExtValue; import com.evolveum.midpoint.repo.sql.data.common.container.RTrigger; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; @@ -27,21 +35,39 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; -import com.evolveum.midpoint.repo.sql.util.*; +import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; +import com.evolveum.midpoint.repo.sql.util.EntityState; +import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; +import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; -import org.hibernate.annotations.*; +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.NamedQueries; import org.hibernate.annotations.NamedQuery; +import org.hibernate.annotations.Where; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Embedded; import javax.persistence.Entity; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; import javax.persistence.Index; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Lob; +import javax.persistence.OneToMany; import javax.persistence.Table; +import javax.persistence.Transient; import javax.xml.datatype.XMLGregorianCalendar; import java.io.Serializable; import java.util.Collection; @@ -79,6 +105,8 @@ @NamedQuery(name = "delete.campaignCase", query = "delete RAccessCertificationCase c where c.ownerOid = :oid and c.id = :id"), @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), }) +@QueryEntity(anyElements = { + @VirtualAny(jaxbNameLocalPart = "extension")}) @Entity @Table(name = "m_object", indexes = { @Index(name = "iObjectNameOrig", columnList = "name_orig"), diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java index 6ad2bde8676..b8186251137 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java @@ -27,6 +27,8 @@ import com.evolveum.midpoint.repo.sql.data.common.enums.RShadowKind; import com.evolveum.midpoint.repo.sql.data.common.enums.RSynchronizationSituation; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -54,6 +56,8 @@ indexes = {@Index(name = "iShadowResourceRef", columnNames = "resourceRef_targetOid"), @Index(name = "iShadowDead", columnNames = "dead")}) @ForeignKey(name = "fk_shadow") +@QueryEntity(anyElements = { + @VirtualAny(jaxbNameLocalPart = "attributes")}) public class RShadow extends RObject implements OperationResult { private static final Trace LOGGER = TraceManager.getTrace(RShadow.class); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/QueryEntity.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/QueryEntity.java index 3c5ad8e7a73..36bc02bf279 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/QueryEntity.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/QueryEntity.java @@ -38,5 +38,7 @@ VirtualEntity[] entities() default {}; + VirtualAny[] anyElements() default {}; + VirtualReference[] references() default {}; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java similarity index 90% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java index 75eae84cc6c..54b95f398b4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Any.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2.definition; +package com.evolveum.midpoint.repo.sql.query.definition; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; @@ -25,10 +25,11 @@ /** * @author lazyman + * @author mederly */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) -public @interface Any { +public @interface VirtualAny { String jaxbNameNamespace() default SchemaConstantsGenerated.NS_COMMON; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index cb401e19549..2af280db8e8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -37,6 +37,7 @@ import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; @@ -193,6 +194,8 @@ private Restriction findAndCreateRestriction(T filter, Validate.notNull(filter); Validate.notNull(context); + LOGGER.trace("Determining restriction for filter {}", filter); + String alias = context.getHibernateQuery().getPrimaryEntityAlias(); // the order of processing restrictions can be important, so we do the selection via handwritten code @@ -210,12 +213,12 @@ private Restriction findAndCreateRestriction(T filter, } else if (filter instanceof TypeFilter) { restriction = new TypeRestriction(); } else if (filter instanceof RefFilter) { - ItemPath fullPath = new ItemPath(parent.getItemPathForChildren(), ((RefFilter) filter).getFullPath()); + ItemPath fullPath = getFullPath(parent, ((RefFilter) filter).getFullPath()); EntityDefinition entityDefinition = context.findProperEntityDefinition(fullPath); restriction = new ReferenceRestriction(entityDefinition, alias, entityDefinition); } else if (filter instanceof ValueFilter) { ValueFilter valFilter = (ValueFilter) filter; - ItemPath fullPath = new ItemPath(parent.getItemPathForChildren(), valFilter.getFullPath()); + ItemPath fullPath = getFullPath(parent, valFilter.getFullPath()); ProperDefinitionSearchResult propDef = context.findProperDefinition(fullPath, PropertyDefinition.class); if (propDef != null && propDef.getItemDefinition() != null) { @@ -227,10 +230,9 @@ private Restriction findAndCreateRestriction(T filter, } else { EntityDefinition entityDefinition = context.findProperEntityDefinition(fullPath); JpaDefinitionPath jpaDefinitionPath = entityDefinition.translatePath(fullPath); - if (fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) || - fullPath.first().equivalent(new NameItemPathSegment(ShadowType.F_ATTRIBUTES)) || - jpaDefinitionPath.containsAnyDefinition()) { - restriction = new AnyPropertyRestriction(entityDefinition, alias, entityDefinition); + AnyDefinition anyDefinition = jpaDefinitionPath.getAnyDefinition(); + if (anyDefinition != null) { + restriction = new AnyPropertyRestriction(anyDefinition, entityDefinition, alias, entityDefinition); } else { throw new QueryException("Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); } @@ -246,9 +248,19 @@ private Restriction findAndCreateRestriction(T filter, restriction.setContext(context); restriction.setParent(parent); restriction.setFilter(filter); + + LOGGER.trace("Restriction for {} is {}", filter.getClass().getSimpleName(), restriction); return restriction; } + private ItemPath getFullPath(Restriction parent, ItemPath fullPath) { + if (parent == null) { + return fullPath; + } else { + return new ItemPath(parent.getItemPathForChildren(), fullPath); + } + } + private void interpretPagingAndSorting(ObjectQuery query, InterpretationContext context, boolean countingObjects) { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String rootAlias = hibernateQuery.getPrimaryEntityAlias(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 903e8be87f8..65233fe83ea 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -20,6 +20,15 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.any.RAssignmentExtension; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualProperty; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualPropertyDefinition; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualReference; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.constants.ObjectTypes; @@ -115,6 +124,11 @@ private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpa } + for (VirtualAny any : qEntity.anyElements()) { + VirtualAnyDefinition def = new VirtualAnyDefinition(new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart())); + entityDef.addDefinition(def); + } + for (VirtualCollection collection : qEntity.collections()) { QName jaxbName = createQName(collection.jaxbName()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java index dcf56e8a9e3..b989b17498f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java @@ -17,9 +17,11 @@ package com.evolveum.midpoint.repo.sql.query2.definition; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query.restriction.PathTranslation; import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.Holder; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import javax.xml.namespace.QName; @@ -28,6 +30,8 @@ */ public abstract class Definition implements DebugDumpable { + private static final Trace LOGGER = TraceManager.getTrace(Definition.class); + //jaxb private QName jaxbName; private Class jaxbType; @@ -128,8 +132,26 @@ public Definition nextDefinition(Holder pathHolder) { return null; } + // beware, path translation can end e.g. in ANY element (extension, attributes) + // also, beware of parent links and cross-entity links public JpaDefinitionPath translatePath(ItemPath path) { - return null; + Holder pathHolder = new Holder<>(path); + JpaDefinitionPath jpaPath = new JpaDefinitionPath(); + + Definition currentDefinition = this; + for (;;) { + ItemPath currentPath = pathHolder.getValue(); + if (currentDefinition == null || currentPath == null || currentPath.isEmpty()) { + LOGGER.trace("ItemPath {} translated to JpaDefinitionPath {}; remainder {} (started in {})", path, jpaPath, currentPath, this.getShortInfo()); + return jpaPath; + } + ItemPath origPath = pathHolder.getValue(); + currentDefinition = currentDefinition.nextDefinition(pathHolder); + LOGGER.trace("nextDefinition on {} returned {}", origPath, currentDefinition != null ? currentDefinition.getShortInfo() : "(null)"); + if (currentDefinition != null) { + jpaPath.add(currentDefinition); + } + } } /** @@ -148,6 +170,9 @@ public D findDefinition(ItemPath path, Class type) { return null; } } + if (currentDefinition instanceof AnyDefinition && type.isAssignableFrom(AnyDefinition.class)) { + return (D) currentDefinition; + } currentDefinition = currentDefinition.nextDefinition(pathHolder); if (currentDefinition == null) { return null; @@ -158,4 +183,8 @@ public D findDefinition(ItemPath path, Class type) { public D findDefinition(QName jaxbName, Class type) { return null; } + + public String getShortInfo() { + return getDebugDumpClassName() + ":" + DebugUtil.formatElementName(getJaxbName()) + ":" + getJpaName(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java index 98d6bbc4075..f663dc7ac31 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java @@ -166,22 +166,4 @@ public Definition nextDefinition(Holder pathHolder) { } } - // beware, path translation can end e.g. in ANY element (extension, attributes) - // also, beware of parent links and cross-entity links - @Override - public JpaDefinitionPath translatePath(ItemPath path) { - Holder pathHolder = new Holder<>(path); - JpaDefinitionPath jpaPath = new JpaDefinitionPath(); - - Definition currentDefinition = this; - for (;;) { - ItemPath currentPath = pathHolder.getValue(); - if (currentPath == null || currentPath.isEmpty()) { - return jpaPath; - } - jpaPath.add(currentDefinition); - currentDefinition = nextDefinition(pathHolder); - } - } - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java deleted file mode 100644 index 3576bf70db8..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbName.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.schema.SchemaConstantsGenerated; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author lazyman - */ -@Target({TYPE, METHOD, FIELD}) -@Retention(RUNTIME) -public @interface JaxbName { - - String namespace() default SchemaConstantsGenerated.NS_COMMON; - - String localPart(); -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java deleted file mode 100644 index e2cec2dff58..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JaxbType.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author lazyman - */ -@Target({TYPE, METHOD, FIELD}) -@Retention(RUNTIME) -public @interface JaxbType { - - Class type(); -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java index 157c6afd077..e426df5a368 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java @@ -16,9 +16,6 @@ package com.evolveum.midpoint.repo.sql.query2.definition; -import com.evolveum.midpoint.repo.sql.query.definition.*; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaNamePath; - import java.util.ArrayList; import java.util.List; @@ -47,12 +44,34 @@ public Definition get(int i) { return definitions.get(i); } - public boolean containsAnyDefinition() { + public AnyDefinition getAnyDefinition() { for (Definition definition : definitions) { if (definition instanceof AnyDefinition) { - return true; + return (AnyDefinition) definition; + } + } + return null; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + boolean first = true; + + for (Definition definition : definitions) { + if (first) { + first = false; + } else { + sb.append(", "); + } + if (definition != null) { + sb.append(definition.getShortInfo()); + } else { + sb.append("null"); // Just to catch errors in translations } } - return false; + sb.append(']'); + return sb.toString(); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java deleted file mode 100644 index 8561e1d6b57..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/QueryEntity.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author lazyman - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface QueryEntity { - - JaxbName jaxbName() default @JaxbName(localPart = ""); - - Class jaxbType() default Object.class; - - VirtualProperty[] properties() default {}; - - VirtualCollection[] collections() default {}; - - VirtualEntity[] entities() default {}; - - VirtualReference[] references() default {}; -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java similarity index 62% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java index 66440282424..cca265f9de0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualQueryParam.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java @@ -16,22 +16,14 @@ package com.evolveum.midpoint.repo.sql.query2.definition; -import java.io.Serializable; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import javax.xml.namespace.QName; /** - * @author lazyman + * @author mederly */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface VirtualQueryParam { +public class VirtualAnyDefinition extends AnyDefinition { - String name(); - - Class type(); - - String value(); + public VirtualAnyDefinition(QName jaxbName) { + super(jaxbName, null, null, null); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java deleted file mode 100644 index 5c3ebd02624..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollection.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author lazyman - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface VirtualCollection { - - JaxbName jaxbName(); - - Class jaxbType(); - - String jpaName(); - - Class jpaType(); - - VirtualQueryParam[] additionalParams() default {}; - - Class collectionType(); -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java index fca23badb2c..c799b8421ad 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java @@ -16,6 +16,8 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; + import javax.xml.namespace.QName; /** diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java deleted file mode 100644 index de17e64c894..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntity.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.io.Serializable; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author lazyman - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface VirtualEntity { - - JaxbName jaxbName(); - - Class jaxbType(); - - String jpaName(); - - Class jpaType(); - - VirtualQueryParam[] additionalParams() default {}; -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java index 9a4c545575f..258f934cd13 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java @@ -16,6 +16,8 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; + import javax.xml.namespace.QName; /** diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java deleted file mode 100644 index 0ce2fbf4b99..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualProperty.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.io.Serializable; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author lazyman - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface VirtualProperty { - - JaxbName jaxbName(); - - Class jaxbType(); - - String jpaName(); - - Class jpaType(); - - VirtualQueryParam[] additionalParams() default {}; -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java index 4f475d5a984..7bb3666f5c5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java @@ -16,6 +16,8 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; + import javax.xml.namespace.QName; /** diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java deleted file mode 100644 index f20fda0a1db..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualReference.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.io.Serializable; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author lazyman - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface VirtualReference { - - JaxbName jaxbName(); - - Class jaxbType(); - - String jpaName(); - - Class jpaType(); - - VirtualQueryParam[] additionalParams() default {}; -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index 81b7240b4c9..a0c8663fa53 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -182,7 +182,7 @@ public String createAlias(String name, boolean isEntity) { } private boolean hasAlias(String alias) { - if (primaryEntity.containsAlias(alias)) { + if (primaryEntity != null && primaryEntity.containsAlias(alias)) { return true; } for (EntityReference other : otherEntities) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java index 5a9a4e85f5e..e3ac7a52d15 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/JoinSpecification.java @@ -57,7 +57,7 @@ public static void dumpToHql(StringBuilder sb, List joins, in if (first) { first = false; } else { - sb.append(",\n"); + sb.append("\n"); } HibernateQuery.indent(sb, indent); join.dumpToHql(sb); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java index 053cd79540b..4d0a108445c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/QueryParameterValue.java @@ -42,4 +42,22 @@ public Type getType() { public Object getValue() { return value; } + + public String debugDump() { + StringBuilder sb = new StringBuilder(); + sb.append(value); + if (value instanceof Enum) { + sb.append(" ("); + sb.append(value.getClass().getName()); + sb.append('.'); + sb.append(((Enum) value).name()); + sb.append(')'); + } + if (type != null) { + sb.append(" (type = "); + sb.append(type); + sb.append(")"); + } + return sb.toString(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java index 9f4fd41e45f..c5e551b40d2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java @@ -25,13 +25,14 @@ import com.evolveum.midpoint.repo.sql.query2.hqm.condition.NotCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.SimpleComparisonCondition; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.MatchMode; import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; -import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -42,6 +43,8 @@ */ public class RootHibernateQuery extends HibernateQuery { + private static final Trace LOGGER = TraceManager.getTrace(RootHibernateQuery.class); + private Map parameters = new HashMap<>(); private Integer maxResults; private Integer firstResult; @@ -74,14 +77,25 @@ private String findFreeName(String prefix) { public Query getAsHqlQuery(Session session) { String text = getAsHqlText(0); + LOGGER.trace("HQL text generated:\n{}", text); Query query = session.createQuery(text); for (Map.Entry parameter : parameters.entrySet()) { String name = parameter.getKey(); QueryParameterValue parameterValue = parameter.getValue(); - if (parameterValue.getType() != null) { - query.setParameter(name, parameterValue.getValue(), parameterValue.getType()); + LOGGER.trace("Parameter {} = {}", name, parameterValue.debugDump()); + + if (parameterValue.getValue() instanceof Collection) { + if (parameterValue.getType() != null) { + query.setParameterList(name, (Collection) parameterValue.getValue(), parameterValue.getType()); + } else { + query.setParameterList(name, (Collection) parameterValue.getValue()); + } } else { - query.setParameter(name, parameterValue.getValue()); + if (parameterValue.getType() != null) { + query.setParameter(name, parameterValue.getValue(), parameterValue.getType()); + } else { + query.setParameter(name, parameterValue.getValue()); + } } } if (maxResults != null) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java index d065b239e07..6698c3c87c8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/DefaultMatcher.java @@ -30,6 +30,6 @@ public class DefaultMatcher extends Matcher { public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, T value, String matcher) throws QueryException { - return basicMatch(null, operation, propertyName, value, false); + return basicMatch(hibernateQuery, operation, propertyName, value, false); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java index 55f5af566fd..dbb8386a0f3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/PolyStringMatcher.java @@ -53,29 +53,29 @@ public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperati if (StringUtils.isEmpty(matcher) || STRICT.equals(matcher) || STRICT_IGNORE_CASE.equals(matcher)) { AndCondition conjunction = hibernateQuery.createAnd(); - conjunction.add(createOrigMatch(operation, propertyName, value, ignoreCase)); - conjunction.add(createNormMatch(operation, propertyName, value, ignoreCase)); + conjunction.add(createOrigMatch(hibernateQuery, operation, propertyName, value, ignoreCase)); + conjunction.add(createNormMatch(hibernateQuery, operation, propertyName, value, ignoreCase)); return conjunction; } else if (ORIG.equals(matcher) || ORIG_IGNORE_CASE.equals(matcher)) { - return createOrigMatch(operation, propertyName, value, ignoreCase); + return createOrigMatch(hibernateQuery, operation, propertyName, value, ignoreCase); } else if (NORM.equals(matcher) || NORM_IGNORE_CASE.equals(matcher)) { - return createNormMatch(operation, propertyName, value, ignoreCase); + return createNormMatch(hibernateQuery, operation, propertyName, value, ignoreCase); } else { throw new QueryException("Unknown matcher '" + matcher + "'."); } } - private Condition createNormMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, + private Condition createNormMatch(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, PolyString value, boolean ignoreCase) throws QueryException { String realValue = value != null ? value.getNorm() : null; - return basicMatch(null, operation, propertyName + '.' + RPolyString.F_NORM, realValue, ignoreCase); + return basicMatch(hibernateQuery, operation, propertyName + '.' + RPolyString.F_NORM, realValue, ignoreCase); } - private Condition createOrigMatch(ItemRestrictionOperation operation, String propertyName, PolyString value, + private Condition createOrigMatch(RootHibernateQuery hibernateQuery, ItemRestrictionOperation operation, String propertyName, PolyString value, boolean ignoreCase) throws QueryException { String realValue = value != null ? value.getOrig() : null; - return basicMatch(null, operation, propertyName + '.' + RPolyString.F_ORIG, realValue, ignoreCase); + return basicMatch(hibernateQuery, operation, propertyName + '.' + RPolyString.F_ORIG, realValue, ignoreCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java index 5279cd03eb7..83df46355c6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/StringMatcher.java @@ -36,6 +36,6 @@ public Condition match(RootHibernateQuery hibernateQuery, ItemRestrictionOperati boolean ignoreCase = IGNORE_CASE.equalsIgnoreCase(matcher); - return basicMatch(null, operation, propertyName, value, ignoreCase); + return basicMatch(hibernateQuery, operation, propertyName, value, ignoreCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index ee2f4c0a05c..43678540cbf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -29,12 +29,14 @@ import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; import org.hibernate.criterion.Conjunction; import org.hibernate.criterion.Restrictions; @@ -49,8 +51,12 @@ public class AnyPropertyRestriction extends ItemRestriction { private static final Trace LOGGER = TraceManager.getTrace(AnyPropertyRestriction.class); - public AnyPropertyRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { + private AnyDefinition anyDefinition; + + public AnyPropertyRestriction(AnyDefinition anyDefinition, EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { super(rootEntityDefinition, startPropertyPath, startEntityDefinition); + Validate.notNull(anyDefinition, "anyDefinition"); + this.anyDefinition = anyDefinition; } @Override @@ -65,8 +71,14 @@ public Condition interpretInternal(String hqlPath) throws QueryException { } ItemPath fullPath = getFullPath(filter.getFullPath()); // TODO does not work for cross-entities! - RObjectExtensionType ownerType = fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) ? - RObjectExtensionType.EXTENSION : RObjectExtensionType.ATTRIBUTES; + + RObjectExtensionType ownerType; + if (anyDefinition instanceof VirtualAnyDefinition) { + ownerType = fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) ? + RObjectExtensionType.EXTENSION : RObjectExtensionType.ATTRIBUTES; // TODO write more nicely (e.g. using VirtualAnyDefinition field) + } else { + ownerType = null; // assignment extension has no ownerType + } String anyAssociationName = null; // longs, strings, ... try { anyAssociationName = RAnyConverter.getAnySetType(itemDefinition); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java index 668d0e25110..50bd19602b1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java @@ -45,12 +45,7 @@ public CollectionRestriction(EntityDefinition rootEntityDefinition, String alias public Condition interpretInternal(String hqlPath) throws QueryException { Object value = getValueFromFilter(filter, (PropertyDefinition) collectionDefinition.getDefinition()); - //custom propertyPath handling for PolyString (it's embedded entity, not a primitive) - if (value instanceof PolyString) { - return createCondition(hqlPath, value, filter); - } - - return createCondition(hqlPath + ".elements", value, filter); + return createCondition(hqlPath, value, filter); // TODO what about not-null ? } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index 6eabed7ab6c..3bef60f6759 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -29,6 +29,7 @@ import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; @@ -40,7 +41,6 @@ import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.VirtualQueryParam; import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; @@ -59,6 +59,7 @@ import javax.xml.namespace.QName; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; /** @@ -148,28 +149,41 @@ private String prepareJoins(ItemPath relativePath) throws QueryException { JpaDefinitionPath jpaDefinitionPath = startEntityDefinition.translatePath(relativePath); String currentHqlPath = startPropertyPath; - for (Definition definition : jpaDefinitionPath.getDefinitions()) { + List definitions = jpaDefinitionPath.getDefinitions(); + for (int i = 0; i < definitions.size(); i++) { + Definition definition = definitions.get(i); if (definition instanceof EntityDefinition) { EntityDefinition entityDef = (EntityDefinition) definition; if (!entityDef.isEmbedded()) { LOGGER.trace("Adding join for '{}' to context", entityDef.getJpaName()); currentHqlPath = addJoin(entityDef, currentHqlPath); + } else { + currentHqlPath += "." + entityDef.getJpaName(); } } else if (definition instanceof AnyDefinition) { - LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); - currentHqlPath = addJoin(definition, currentHqlPath); + if (definition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes + LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); + currentHqlPath = addJoin(definition, currentHqlPath); + } break; } else if (definition instanceof CollectionDefinition) { LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); currentHqlPath = addJoin(definition, currentHqlPath); + + // Because the next definition in the chain is the one that is referred to by this Collection + // (either property, reference or entity), we need to skip it: If it's entity, we have already + // joined it - and if it's property/reference, we would break the cycle even so + i++; + } else if (definition instanceof PropertyDefinition || definition instanceof ReferenceDefinition) { - break; + break; // quite redundant, as this is the last item in the chain } else { - throw new QueryException("Not implemented yet."); + throw new QueryException("Not implemented yet: " + definition); } // TODO entity crossjoin references (when crossing object boundaries) } + LOGGER.trace("prepareJoins({}) returning currentHqlPath of {}", relativePath, currentHqlPath); return currentHqlPath; } @@ -233,11 +247,13 @@ protected String addJoinAny(String currentHqlPath, String anyAssociationName, QN String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); - Condition condition = hibernateQuery.createAnd( - hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType), - hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); + AndCondition conjunction = hibernateQuery.createAnd(); + if (ownerType != null) { // null for assignment extensions + conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType)); + } + conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); - entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); + entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); return joinedItemAlias; } @@ -275,7 +291,7 @@ protected Condition createCondition(String propertyName, Object value, ValueFilt matchingRule = filter.getMatchingRule().getLocalPart(); } - return matcher.match(null, operation, propertyName, value, matchingRule); + return matcher.match(context.getHibernateQuery(), operation, propertyName, value, matchingRule); } protected Object getValue(List values) { @@ -319,7 +335,7 @@ protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) } if (value != null && !def.getJaxbType().isAssignableFrom(value.getClass())) { - throw new QueryException("Value should by type of '" + def.getJaxbType() + "' but it's '" + throw new QueryException("Value should be type of '" + def.getJaxbType() + "' but it's '" + value.getClass() + "', filter '" + filter + "'."); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java index d3f8383e538..15627b08479 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -72,7 +72,7 @@ public Condition interpret() throws QueryException { "where " + "ref.referenceType = " + nameOf(RReferenceOwner.OBJECT_PARENT_ORG) + " and " + "ref.targetOid in (" + - "select descendantOid from ROrgClosure where ancestorOid = :" + orgOidParamName; + "select descendantOid from ROrgClosure where ancestorOid = :" + orgOidParamName + ")"; } return hibernateQuery.createIn(context.getCurrentHqlPropertyPath() + ".oid", oidQueryText); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index e52f09e8965..bb405108015 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -25,13 +25,18 @@ import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.ProperDefinitionSearchResult; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import javax.xml.namespace.QName; import java.util.List; @@ -41,6 +46,8 @@ */ public class ReferenceRestriction extends ItemRestriction { + private static final Trace LOGGER = TraceManager.getTrace(ReferenceRestriction.class); + public ReferenceRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { super(rootEntityDefinition, startPropertyPath, startEntityDefinition); } @@ -49,6 +56,8 @@ public ReferenceRestriction(EntityDefinition rootEntityDefinition, String startP @Override public Condition interpretInternal(String hqlPath) throws QueryException { + LOGGER.trace("interpretInternal starting with hqlPath = {}", hqlPath); + List values = filter.getValues(); if (values != null && values.size() > 1) { throw new QueryException("Ref filter '" + filter + "' contain more than one reference value (which is not supported for now)."); @@ -67,7 +76,14 @@ public Condition interpretInternal(String hqlPath) throws QueryException { } Definition definition = defResult.getItemDefinition(); // actually, we cannot expect ReferenceDefinition here, because e.g. linkRef has a CollectionDefinition - String propertyFullNamePrefix = hqlPath + "." + definition.getJpaName() + "."; + String propertyFullNamePrefix; + if (definition instanceof CollectionDefinition) { + propertyFullNamePrefix = hqlPath + "."; + } else if (definition instanceof ReferenceDefinition) { + propertyFullNamePrefix = hqlPath + "." + definition.getJpaName() + "."; + } else { + throw new IllegalStateException("Unexpected kind of Definition while processing ReferenceRestriction: " + definition); + } String refValueOid = null; QName refValueRelation = null; From 7165cc64e64741b0479f92729d5b013a1667f3b7 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 24 Nov 2015 23:16:06 +0100 Subject: [PATCH 013/116] New "Exists" filter. Further refactoring/cleanup of new query interpreter. --- .../midpoint/prism/path/ItemPath.java | 4 + .../midpoint/prism/query/EqualFilter.java | 6 +- .../midpoint/prism/query/ExistsFilter.java | 151 +++++++ .../midpoint/prism/query/FilterUtils.java | 58 +++ .../midpoint/prism/query/GreaterFilter.java | 16 +- .../midpoint/prism/query/InFilter.java | 2 +- .../midpoint/prism/query/LessFilter.java | 8 +- .../midpoint/prism/query/RefFilter.java | 12 +- .../midpoint/prism/query/SubstringFilter.java | 4 +- .../midpoint/prism/query/ValueFilter.java | 28 -- .../repo/sql/SqlRepositoryServiceImpl.java | 10 +- .../repo/sql/data/common/RObject.java | 2 +- .../repo/sql/data/common/RShadow.java | 2 +- .../repo/sql/query/definition/VirtualAny.java | 4 + .../sql/query2/DefinitionSearchResult.java | 48 +++ .../sql/query2/InterpretationContext.java | 117 +----- .../repo/sql/query2/InterpreterHelper.java | 243 ++++++++++++ .../query2/ProperDefinitionSearchResult.java | 29 +- .../sql/query2/QueryDefinitionRegistry2.java | 68 +++- .../repo/sql/query2/QueryEngine2.java | 5 - .../repo/sql/query2/QueryInterpreter2.java | 136 ++++--- .../sql/query2/definition/AnyDefinition.java | 12 + .../definition/ClassDefinitionParser.java | 4 +- .../definition/CollectionDefinition.java | 5 +- .../sql/query2/definition/Definition.java | 99 +++-- ...efinitionPath.java => DefinitionPath.java} | 2 +- .../query2/definition/EntityDefinition.java | 92 +++-- .../query2/definition/PathTranslation.java | 12 +- .../query2/definition/PropertyDefinition.java | 8 + .../definition/ReferenceDefinition.java | 9 + .../definition/VirtualAnyDefinition.java | 13 +- .../repo/sql/query2/hqm/HibernateQuery.java | 2 +- .../query2/restriction/AndRestriction.java | 5 + .../restriction/AnyPropertyRestriction.java | 24 +- .../restriction/CollectionRestriction.java | 19 +- .../query2/restriction/ExistsRestriction.java | 76 ++++ .../query2/restriction/InOidRestriction.java | 10 +- .../query2/restriction/ItemRestriction.java | 371 +----------------- .../restriction/ItemValueRestriction.java | 217 ++++++++++ .../restriction/LogicalRestriction.java | 5 + .../restriction/NaryLogicalRestriction.java | 8 +- .../query2/restriction/NotRestriction.java | 5 + .../sql/query2/restriction/OrRestriction.java | 8 +- .../query2/restriction/OrgRestriction.java | 17 +- .../restriction/PropertyRestriction.java | 10 +- .../restriction/ReferenceRestriction.java | 32 +- .../sql/query2/restriction/Restriction.java | 131 ++++++- .../query2/restriction/TypeRestriction.java | 10 +- .../restriction/UnaryLogicalRestriction.java | 7 +- 49 files changed, 1384 insertions(+), 782 deletions(-) create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FilterUtils.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{JpaDefinitionPath.java => DefinitionPath.java} (98%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index c17dc9a3967..dedc0118276 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -333,6 +333,10 @@ public static boolean isNullOrEmpty(ItemPath itemPath) { return itemPath == null || itemPath.isEmpty(); } + public static boolean containsSingleNameSegment(ItemPath path) { + return path != null && path.size() == 1 && path.first() instanceof NameItemPathSegment; + } + public enum CompareResult { EQUIVALENT, SUPERPATH, diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java index c8a93bf055f..1a45e34c2e7 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java @@ -120,13 +120,13 @@ public static EqualFilter createEqual(ItemPath path, PrismPropertyDefinit public static EqualFilter createEqual(ItemPath parentPath, PrismContainerDefinition containerDef, PrismPropertyValue values) throws SchemaException { - PrismPropertyDefinition propertyDef = (PrismPropertyDefinition) findItemDefinition(parentPath, containerDef); + PrismPropertyDefinition propertyDef = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createEqual(parentPath, propertyDef, values); } public static EqualFilter createEqual(ItemPath itemPath, PrismContainerDefinition containerDef, T realValues) throws SchemaException { - PrismPropertyDefinition propertyDef = (PrismPropertyDefinition) findItemDefinition(itemPath, containerDef); + PrismPropertyDefinition propertyDef = (PrismPropertyDefinition) FilterUtils.findItemDefinition(itemPath, containerDef); return createEqual(itemPath, propertyDef, realValues); } @@ -148,7 +148,7 @@ public static EqualFilter createEqual(ItemPath p public static EqualFilter createEqual(ItemPath propertyPath, Class type, PrismContext prismContext, QName matchingRule, T realValue) { - PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) findItemDefinition(propertyPath, type, prismContext); + PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(propertyPath, type, prismContext); return createEqual(propertyPath, propertyDefinition, matchingRule, realValue); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java new file mode 100644 index 00000000000..705c42ed95a --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; + +/** + * TODO think about creating abstract ItemFilter (ItemRelatedFilter) for this filter and ValueFilter. + * + * @author lazyman + * @author mederly + */ +public class ExistsFilter extends ObjectFilter { + + private ItemPath fullPath; + private ItemDefinition definition; + private ObjectFilter filter; + + public ExistsFilter(ItemPath fullPath, ItemDefinition definition, ObjectFilter filter) { + this.fullPath = fullPath; + this.definition = definition; + this.filter = filter; + checkConsistence(); + } + + public ItemPath getFullPath() { + return fullPath; + } + + public ItemDefinition getDefinition() { + return definition; + } + + public ObjectFilter getFilter() { + return filter; + } + + public static ExistsFilter createEqual(ItemPath itemPath, PrismContainerDefinition containerDef, + ObjectFilter filter) throws SchemaException { + ItemDefinition itemDefinition = FilterUtils.findItemDefinition(itemPath, containerDef); + return new ExistsFilter(itemPath, itemDefinition, filter); + } + + @Override + public ObjectFilter clone() { + ObjectFilter f = filter != null ? filter.clone() : null; + return new ExistsFilter(fullPath, definition, f); + } + + @Override + public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkConsistence() { + if (fullPath == null || fullPath.isEmpty()) { + throw new IllegalArgumentException("Null or empty path in "+this); + } + if (definition == null) { + throw new IllegalArgumentException("Null definition in "+this); + } + // null subfilter is legal. It means "ALL". + if (filter != null) { + filter.checkConsistence(); + } + } + + @Override + public String debugDump() { + return debugDump(0); + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append("EXISTS: "); + sb.append(fullPath); + sb.append('\n'); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("DEF: "); + if (getDefinition() != null) { + sb.append(getDefinition().toString()); + } else { + sb.append("null"); + } + if (filter != null) { + sb.append(filter.debugDump(indent + 1)); + } + + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ExistsFilter)) return false; + + ExistsFilter that = (ExistsFilter) o; + + if (fullPath != null ? !fullPath.equals(that.fullPath) : that.fullPath != null) return false; + if (definition != null ? !definition.equals(that.definition) : that.definition != null) return false; + return !(filter != null ? !filter.equals(that.filter) : that.filter != null); + + } + + @Override + public int hashCode() { + int result = fullPath != null ? fullPath.hashCode() : 0; + result = 31 * result + (definition != null ? definition.hashCode() : 0); + result = 31 * result + (filter != null ? filter.hashCode() : 0); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("EXISTS("); + sb.append(PrettyPrinter.prettyPrint(fullPath)); + sb.append(","); + sb.append(filter); + sb.append(")"); + return sb.toString(); + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FilterUtils.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FilterUtils.java new file mode 100644 index 00000000000..bf8122b7eb1 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FilterUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query; + +import com.evolveum.midpoint.prism.ComplexTypeDefinition; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; + +/** + * @author mederly + */ +public class FilterUtils { + + static ItemDefinition findItemDefinition(ItemPath itemPath, PrismContainerDefinition containerDef) { + ItemDefinition itemDef = containerDef.findItemDefinition(itemPath); + if (itemDef == null) { + throw new IllegalStateException("No definition for item " + itemPath + " in container definition " + + containerDef); + } + + return itemDef; + } + + static ItemDefinition findItemDefinition(ItemPath parentPath, ComplexTypeDefinition complexTypeDefinition) { + ItemDefinition itemDef = complexTypeDefinition.findItemDefinition(parentPath); + if (itemDef == null) { + throw new IllegalStateException("No definition for item " + parentPath + " in complex type definition " + + complexTypeDefinition); + } + return itemDef; + } + + static ItemDefinition findItemDefinition(ItemPath parentPath, Class type, PrismContext prismContext) { + ComplexTypeDefinition complexTypeDefinition = prismContext.getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(type); + if (complexTypeDefinition == null) { + // TODO SchemaException instead? + throw new IllegalStateException("Definition of complex type " + type + " couldn't be not found"); + } + return findItemDefinition(parentPath, complexTypeDefinition); + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java index 3b9e302125d..7d4b0bcf9b1 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java @@ -16,25 +16,15 @@ package com.evolveum.midpoint.prism.query; -import java.util.ArrayList; -import java.util.List; - import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.PrismContainerValue; -import org.apache.commons.lang.Validate; -import org.w3c.dom.Element; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Objectable; -import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.DebugUtil; @@ -56,7 +46,7 @@ public static GreaterFilter createGreater(ItemPath par public static GreaterFilter createGreater(ItemPath parentPath, PrismObjectDefinition containerDef, PrismPropertyValue value, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) findItemDefinition(parentPath, containerDef); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createGreater(parentPath, def, value, equals); } @@ -72,7 +62,7 @@ public static GreaterFilter createGreater(ItemPath parentPath, PrismProperty public static GreaterFilter createGreater(ItemPath parentPath, PrismObjectDefinition containerDef, T realValue, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) findItemDefinition(parentPath, containerDef); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createGreater(parentPath, def, realValue, equals); } @@ -84,7 +74,7 @@ public static GreaterFilter createGreater(QName proper public static GreaterFilter createGreater(ItemPath path, Class type, PrismContext prismContext, T realValue, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) findItemDefinition(path, type, prismContext); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createGreater(path, def, realValue, equals); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InFilter.java index b12f0edd3a3..fe8aa2e124d 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InFilter.java @@ -53,7 +53,7 @@ public static InFilter createIn(ItemPath path, PrismPropertyDefinition defin public static InFilter createIn(ItemPath path, Class type, PrismContext prismContext, QName matchingRule, V values) { - PrismPropertyDefinition definition = (PrismPropertyDefinition) findItemDefinition(path, type, prismContext); + PrismPropertyDefinition definition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createIn(path, definition, null, values); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java index 71204e8e8e3..31be0f48915 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java @@ -18,11 +18,9 @@ import javax.xml.namespace.QName; -import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; @@ -51,7 +49,7 @@ public static LessFilter createLess(ItemPath parentPat public static LessFilter createLess(ItemPath parentPath, PrismObjectDefinition containerDef, PrismPropertyValue value, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) findItemDefinition(parentPath, containerDef); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createLess(parentPath, def, value, equals); } @@ -71,7 +69,7 @@ public static LessFilter createLess(ItemPath parentPath, PrismPropertyDefini public static LessFilter createLess(ItemPath parentPath, PrismObjectDefinition containerDef, T realValue, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) findItemDefinition(parentPath, containerDef); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createLess(parentPath, def, realValue, equals); } @@ -83,7 +81,7 @@ public static LessFilter createLess(QName propertyName public static LessFilter createLess(ItemPath path, Class type, PrismContext prismContext, T realValue, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) findItemDefinition(path, type, prismContext); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createLess(path, def, realValue, equals); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java index 25e60559ab3..77c9164cb24 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java @@ -24,8 +24,6 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.match.MatchingRule; import org.apache.commons.lang.Validate; import com.evolveum.midpoint.prism.Item; @@ -93,26 +91,26 @@ public static RefFilter createReferenceEqual(ItemPath path, PrismReferenceDefini public static RefFilter createReferenceEqual(QName propertyName, Class type, PrismContext prismContext, String... oids) { ItemPath path = new ItemPath(propertyName); - PrismReferenceDefinition refDefinition = (PrismReferenceDefinition) findItemDefinition(path, type, prismContext); + PrismReferenceDefinition refDefinition = (PrismReferenceDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createReferenceEqual(path, refDefinition, oids); } // beware, creating reference with (oid, ObjectType) may result in not matching a concrete reference of e.g. (oid, RoleType) public static RefFilter createReferenceEqual(ItemPath path, Class type, PrismContext prismContext, String... oids) throws SchemaException { - PrismReferenceDefinition refDefinition = (PrismReferenceDefinition) findItemDefinition(path, type, prismContext); + PrismReferenceDefinition refDefinition = (PrismReferenceDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createReferenceEqual(path, refDefinition, oids); } public static RefFilter createReferenceEqual(ItemPath path, Class type, PrismContext prismContext, PrismReferenceValue... values) throws SchemaException { - PrismReferenceDefinition refDefinition = (PrismReferenceDefinition) findItemDefinition(path, type, prismContext); + PrismReferenceDefinition refDefinition = (PrismReferenceDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createReferenceEqual(path, refDefinition, values); } public static RefFilter createReferenceEqual(ItemPath path, PrismContainerDefinition containerDef, String... oids) { - ItemDefinition itemDef = findItemDefinition(path, containerDef); + ItemDefinition itemDef = FilterUtils.findItemDefinition(path, containerDef); if (!(itemDef instanceof PrismReferenceDefinition)){ throw new IllegalStateException("Bad item definition. Expected that the definition will be instance of prism refenrence definition, but found " + itemDef); @@ -130,7 +128,7 @@ public static RefFilter createReferenceEqual(QName proper ItemPath path = new ItemPath(propertyName); - ItemDefinition itemDef = findItemDefinition(path, type, targetObject.getPrismContext()); + ItemDefinition itemDef = FilterUtils.findItemDefinition(path, type, targetObject.getPrismContext()); if (!(itemDef instanceof PrismReferenceDefinition)){ throw new IllegalStateException("Bad item definition. Expected that the definition will be instance of prism refenrence definition, but found " + itemDef); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java index fb3789bb80f..fa23a1606c0 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java @@ -23,7 +23,6 @@ import javax.xml.namespace.QName; -import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.util.exception.SchemaException; import org.apache.commons.lang.Validate; @@ -32,7 +31,6 @@ import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; @@ -151,7 +149,7 @@ public static SubstringFilter createSubstring(ItemPath public static SubstringFilter createSubstring(ItemPath path, Class clazz, PrismContext prismContext, QName matchingRule, T realValue) { - ItemDefinition itemDefinition = findItemDefinition(path, clazz, prismContext); + ItemDefinition itemDefinition = FilterUtils.findItemDefinition(path, clazz, prismContext); if (!(itemDefinition instanceof PrismPropertyDefinition)){ throw new IllegalStateException("Bad definition. Expected property definition, but got " + itemDefinition); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ValueFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ValueFilter.java index 1b40b231031..b3ebd1c9ab5 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ValueFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ValueFilter.java @@ -118,34 +118,6 @@ public MatchingRule getMatchingRuleFromRegistry(MatchingRuleRegistry matchingRul return matching; } - - static ItemDefinition findItemDefinition(ItemPath itemPath, PrismContainerDefinition containerDef) { - ItemDefinition itemDef = containerDef.findItemDefinition(itemPath); - if (itemDef == null) { - throw new IllegalStateException("No definition for item " + itemPath + " in container definition " - + containerDef); - } - - return itemDef; - } - - static ItemDefinition findItemDefinition(ItemPath parentPath, ComplexTypeDefinition complexTypeDefinition) { - ItemDefinition itemDef = complexTypeDefinition.findItemDefinition(parentPath); - if (itemDef == null) { - throw new IllegalStateException("No definition for item " + parentPath + " in complex type definition " - + complexTypeDefinition); - } - return itemDef; - } - - static ItemDefinition findItemDefinition(ItemPath parentPath, Class type, PrismContext prismContext) { - ComplexTypeDefinition complexTypeDefinition = prismContext.getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(type); - if (complexTypeDefinition == null) { - // TODO SchemaException instead? - throw new IllegalStateException("Definition of complex type " + type + " couldn't be not found"); - } - return findItemDefinition(parentPath, complexTypeDefinition); - } protected void cloneValues(ValueFilter clone) { super.cloneValues(clone); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index eb8c45db3f2..553025f817b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -1004,7 +1004,7 @@ private int countObjectsAttempt(Class type, ObjectQuer longCount = (Number) sqlQuery.uniqueResult(); } else { RQuery rQuery; - if (query.isUseNewQueryInterpreter()) { + if (isUseNewQueryInterpreter(query)) { QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); rQuery = engine.interpret(query, type, null, true, session); } else { @@ -1155,7 +1155,7 @@ private SearchResultList> searchObjectsAtt session = beginReadOnlyTransaction(); RQuery rQuery; - if (query.isUseNewQueryInterpreter()) { + if (isUseNewQueryInterpreter(query)) { QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); rQuery = engine.interpret(query, type, options, false, session); } else { @@ -2175,7 +2175,7 @@ private void searchObjectsIterativeAttempt(Class type, try { session = beginReadOnlyTransaction(); RQuery rQuery; - if (query.isUseNewQueryInterpreter()) { + if (isUseNewQueryInterpreter(query)) { QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); rQuery = engine.interpret(query, type, options, false, session); } else { @@ -2208,6 +2208,10 @@ private void searchObjectsIterativeAttempt(Class type, } } + private boolean isUseNewQueryInterpreter(ObjectQuery query) { + return query == null || query.isUseNewQueryInterpreter(); + } + private void searchObjectsIterativeByPaging(Class type, ObjectQuery query, ResultHandler handler, Collection> options, diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 3263d1d458a..8a20f5bf462 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -106,7 +106,7 @@ @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), }) @QueryEntity(anyElements = { - @VirtualAny(jaxbNameLocalPart = "extension")}) + @VirtualAny(jaxbNameLocalPart = "extension", ownerType = RObjectExtensionType.EXTENSION)}) @Entity @Table(name = "m_object", indexes = { @Index(name = "iObjectNameOrig", columnList = "name_orig"), diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java index b8186251137..0ed6766f00a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RShadow.java @@ -57,7 +57,7 @@ @Index(name = "iShadowDead", columnNames = "dead")}) @ForeignKey(name = "fk_shadow") @QueryEntity(anyElements = { - @VirtualAny(jaxbNameLocalPart = "attributes")}) + @VirtualAny(jaxbNameLocalPart = "attributes", ownerType = RObjectExtensionType.ATTRIBUTES)}) public class RShadow extends RObject implements OperationResult { private static final Trace LOGGER = TraceManager.getTrace(RShadow.class); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java index 54b95f398b4..a6e614ad5c3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualAny.java @@ -16,6 +16,8 @@ package com.evolveum.midpoint.repo.sql.query.definition; +import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import java.lang.annotation.ElementType; @@ -34,4 +36,6 @@ String jaxbNameNamespace() default SchemaConstantsGenerated.NS_COMMON; String jaxbNameLocalPart(); + + RObjectExtensionType ownerType(); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java new file mode 100644 index 00000000000..29d7670dbd2 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class DefinitionSearchResult { + T itemDefinition; // definition of the item itself + ItemPath remainder; // what has remained unresolved of the original search path + + public DefinitionSearchResult(T itemDefinition, ItemPath remainder) { + Validate.notNull(itemDefinition, "itemDefinition"); + this.itemDefinition = itemDefinition; + this.remainder = remainder; + } + + public T getItemDefinition() { + return itemDefinition; + } + + public ItemPath getRemainder() { + return remainder; + } + + public boolean isComplete() { + return ItemPath.isNullOrEmpty(remainder); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index f481d0eec15..50cdc135d49 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -55,12 +55,18 @@ public class InterpretationContext { private PrismContext prismContext; private Session session; + private InterpreterHelper helper = new InterpreterHelper(this); + private Class type; private RootHibernateQuery hibernateQuery; - // path from the root filter to the current one (necessary when finding correct Restriction) - private List currentFilterPath = new ArrayList<>(); + /** + * Definition of the root entity. Root entity corresponds to the ObjectType class that was requested + * by the search operation, or the one that was refined from abstract types (ObjectType, AbstractRoleType, ...) + * in the process of restriction construction. + */ + private EntityDefinition rootEntityDefinition; public InterpretationContext(QueryInterpreter2 interpreter, Class type, PrismContext prismContext, Session session) throws QueryException { @@ -79,14 +85,11 @@ public InterpretationContext(QueryInterpreter2 interpreter, Class ProperDefinitionSearchResult findProperDefinition(ItemPath path, Class clazz) { - QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - Class objectClass = getType(); - if (!Modifier.isAbstract(objectClass.getModifiers())) { - EntityDefinition entityDefinition = registry.findDefinition(getType(), null, EntityDefinition.class); - T pathDefinition = entityDefinition.findDefinition(path, clazz); - return new ProperDefinitionSearchResult<>(entityDefinition, pathDefinition); - } - - //we should try to find property in descendant classes - for (Class type : findOtherPossibleParents()) { - EntityDefinition entityDefinition = registry.findDefinition(type, null, EntityDefinition.class); - T pathDefinition = entityDefinition.findDefinition(path, clazz); - if (pathDefinition != null) { - return new ProperDefinitionSearchResult<>(entityDefinition, pathDefinition); - } - } - return null; - } - - /** - * Similar to the above, but returns only the entity name. - * @param path - * @return - */ - protected EntityDefinition findProperEntityDefinition(ItemPath path) { - ProperDefinitionSearchResult result = findProperDefinition(path, Definition.class); - if (result != null) { - return result.getRootEntityDefinition(); - } else { - return null; - } + public InterpreterHelper getHelper() { + return helper; } - private List> findOtherPossibleParents() { - TypeFilter typeFilter = findTypeFilterParent(); - ObjectTypes typeClass; - if (typeFilter != null) { - typeClass = ObjectTypes.getObjectTypeFromTypeQName(typeFilter.getType()); - } else { - typeClass = ObjectTypes.getObjectType(getType()); - } - - List> classes = new ArrayList<>(); - classes.add(typeClass.getClassDefinition()); // abstract one has to go first - - if (typeClass == ObjectTypes.OBJECT) { - classes.addAll(ObjectTypes.getAllObjectTypes()); - } else if (typeClass == ObjectTypes.FOCUS_TYPE) { - classes.add(UserType.class); - classes.add(AbstractRoleType.class); - classes.add(RoleType.class); - classes.add(OrgType.class); - } else if (typeClass == ObjectTypes.ABSTRACT_ROLE) { - classes.add(RoleType.class); - classes.add(OrgType.class); - } - - LOGGER.trace("Found possible parents {} for entity definitions.", classes); - return classes; + public EntityDefinition getRootEntityDefinition() { + return rootEntityDefinition; } - - private TypeFilter findTypeFilterParent() { - for (int i = currentFilterPath.size()-1; i >= 0; i--) { - ObjectFilter filter = currentFilterPath.get(i); - if (filter instanceof TypeFilter) { - return (TypeFilter) filter; - } - } - return null; - } - - public void pushFilter(ObjectFilter filter) { - currentFilterPath.add(filter); - } - - public void popFilter() { - currentFilterPath.remove(currentFilterPath.size() - 1); - } - - public String getCurrentHqlPropertyPath() { - // preliminary implementation: returns root alias (should be changed when ForValue is implemented) - return hibernateQuery.getPrimaryEntityAlias(); - } - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java new file mode 100644 index 00000000000..c4e8343496c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; +import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.Definition; +import com.evolveum.midpoint.repo.sql.query2.definition.DefinitionPath; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; +import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; + +import javax.xml.namespace.QName; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +/** + * Various generally useful methods used within the interpretation algorithm. + * + * Note that this helper is context-specific. (Probably its name should reflect that.) + * + * @author mederly + */ +public class InterpreterHelper { + + private static final Trace LOGGER = TraceManager.getTrace(InterpreterHelper.class); + + private InterpretationContext context; + + public InterpreterHelper(InterpretationContext interpretationContext) { + this.context = interpretationContext; + } + + // returns property path that can be used to access the item values + public String prepareJoins(ItemPath relativePath, String currentHqlPath, EntityDefinition baseEntityDefinition) throws QueryException { + + LOGGER.trace("Updating query context based on path {}", relativePath); + + /** + * We have to do something like this - examples: + * - activation.administrativeStatus -> (nothing, activation is embedded entity) + * - assignment.targetRef -> "left join u.assignments a with ..." + * - assignment.resourceRef -> "left join u.assignments a with ..." + * - organization -> "left join u.organization o" + * + * Or more complex: + * - assignment.modifyApproverRef -> "left join u.assignments a (...) left join a.modifyApproverRef m (...)" + * - assignment.target.longs -> "left join u.assignments a (...), RObject o left join o.longs (...)" + */ + DefinitionPath definitionPath = baseEntityDefinition.translatePath(relativePath); + + List definitions = definitionPath.getDefinitions(); + for (int i = 0; i < definitions.size(); i++) { + Definition definition = definitions.get(i); + if (definition instanceof EntityDefinition) { + EntityDefinition entityDef = (EntityDefinition) definition; + if (!entityDef.isEmbedded()) { + LOGGER.trace("Adding join for '{}' to context", entityDef.getJpaName()); + currentHqlPath = addJoin(entityDef, currentHqlPath); + } else { + currentHqlPath += "." + entityDef.getJpaName(); + } + } else if (definition instanceof AnyDefinition) { + if (definition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes + LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); + currentHqlPath = addJoin(definition, currentHqlPath); + } + break; + } else if (definition instanceof CollectionDefinition) { + LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); + currentHqlPath = addJoin(definition, currentHqlPath); + + // Because the next definition in the chain is the one that is referred to by this Collection + // (either property, reference or entity), we need to skip it: If it's entity, we have already + // joined it - and if it's property/reference, we would break the cycle even so + i++; + + } else if (definition instanceof PropertyDefinition || definition instanceof ReferenceDefinition) { + break; // quite redundant, as this is the last item in the chain + } else { + throw new QueryException("Not implemented yet: " + definition); + } + // TODO entity crossjoin references (when crossing object boundaries) + } + + LOGGER.trace("prepareJoins({}) returning currentHqlPath of {}", relativePath, currentHqlPath); + return currentHqlPath; + } + + protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) throws QueryException { + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) + String joinedItemJpaName = joinedItemDefinition.getJpaName(); + String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; + String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); + Condition condition = null; + if (joinedItemDefinition instanceof VirtualCollectionDefinition) { + VirtualCollectionDefinition vcd = (VirtualCollectionDefinition) joinedItemDefinition; + List conditions = new ArrayList<>(vcd.getAdditionalParams().length); + for (VirtualQueryParam vqp : vcd.getAdditionalParams()) { + // e.g. name = "assignmentOwner", type = RAssignmentOwner.class, value = "ABSTRACT_ROLE" + Object value = createQueryParamValue(vqp); + Condition c = hibernateQuery.createEq(joinedItemAlias + "." + vqp.name(), value); + conditions.add(c); + } + if (conditions.size() > 1) { + condition = hibernateQuery.createAnd(conditions); + } else if (conditions.size() == 1) { + condition = conditions.iterator().next(); + } + } + entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); + return joinedItemAlias; + } + + /** + * This method provides transformation from {@link String} value defined in + * {@link com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam#value()} to real object. Currently only + * to simple types and enum values. + */ + private Object createQueryParamValue(VirtualQueryParam param) throws QueryException { + Class type = param.type(); + String value = param.value(); + + try { + if (type.isPrimitive()) { + return type.getMethod("valueOf", new Class[]{String.class}).invoke(null, new Object[]{value}); + } + + if (type.isEnum()) { + return Enum.valueOf(type, value); + } + } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException |RuntimeException ex) { + throw new QueryException("Couldn't transform virtual query parameter '" + + param.name() + "' from String to '" + type + "', reason: " + ex.getMessage(), ex); + } + + throw new QueryException("Couldn't transform virtual query parameter '" + + param.name() + "' from String to '" + type + "', it's not yet implemented."); + } + + + public String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) + String joinedItemJpaName = anyAssociationName; + String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; + String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); + + AndCondition conjunction = hibernateQuery.createAnd(); + if (ownerType != null) { // null for assignment extensions + conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType)); + } + conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); + + entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); + return joinedItemAlias; + } + + /** + * Finds the proper definition for (possibly abstract) entity. + * Returns the most abstract entity that can be used. + * Checks for conflicts, such as user.locality vs org.locality. + * + * @param path Path to be found + * @param clazz Kind of definition to be looked for + * @param complete Must the path be completely resolved? + * @return Entity type definition + item definition, or null if nothing was found + */ + public ProperDefinitionSearchResult findProperDefinition(EntityDefinition baseEntityDefinition, + ItemPath path, Class clazz) throws QueryException { + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + ProperDefinitionSearchResult candidateResult = null; + + for (EntityDefinition entityDefinition : findPossibleBaseEntities(baseEntityDefinition, registry)) { + DefinitionSearchResult result = entityDefinition.findDefinition(path, clazz); + if (result != null) { + if (candidateResult == null) { + candidateResult = new ProperDefinitionSearchResult<>(entityDefinition, result); + } else { + // Check for compatibility. As entities are presented from the more abstract to less abstract, + // there is no possibility of false alarm. + if (!candidateResult.getEntityDefinition().isAssignableFrom(entityDefinition)) { + throw new QueryException("Unable to determine root entity for " + path + ": found incompatible candidates: " + + candidateResult.getEntityDefinition().getJpaName() + " and " + + entityDefinition.getJpaName()); + } + } + } + } + return candidateResult; + } + + private List findPossibleBaseEntities(EntityDefinition entityDefinition, QueryDefinitionRegistry2 registry) { + List retval = new ArrayList<>(); + retval.add(entityDefinition); // (possibly) abstract one has to go first + if (entityDefinition.isAbstract()) { // just for efficiency + retval.addAll(registry.getChildrenOf(entityDefinition)); + } + return retval; + } + + /** + * Given existing entity definition and a request for narrowing it, tries to find refined definition. + */ + public EntityDefinition findRestrictedEntityDefinition(EntityDefinition baseEntityDefinition, QName specificTypeName) throws QueryException { + QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); + EntityDefinition specificEntityDefinition = registry.findEntityDefinition(specificTypeName); + if (!baseEntityDefinition.isAssignableFrom(specificEntityDefinition)) { + throw new QueryException("Entity " + baseEntityDefinition.getJpaName() + " cannot be restricted to " + specificEntityDefinition.getJpaName()); + } + return specificEntityDefinition; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java index a17faacff16..4ee27d817b1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java @@ -16,26 +16,33 @@ package com.evolveum.midpoint.repo.sql.query2; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import org.apache.commons.lang.Validate; /** - * @author Pavol + * @author mederly */ -public class ProperDefinitionSearchResult { - EntityDefinition rootEntityDefinition; - T itemDefinition; +public class ProperDefinitionSearchResult extends DefinitionSearchResult { - public ProperDefinitionSearchResult(EntityDefinition rootEntityDefinition, T itemDefinition) { - this.rootEntityDefinition = rootEntityDefinition; - this.itemDefinition = itemDefinition; + EntityDefinition entityDefinition; // entity in which the item was found + + public ProperDefinitionSearchResult(T itemDefinition, ItemPath remainder, EntityDefinition entityDefinition) { + super(itemDefinition, remainder); + Validate.notNull(entityDefinition, "entityDefinition"); + this.entityDefinition = entityDefinition; } - public EntityDefinition getRootEntityDefinition() { - return rootEntityDefinition; + public ProperDefinitionSearchResult(EntityDefinition entityDefinition, DefinitionSearchResult result) { + super(result.getItemDefinition(), result.getRemainder()); + Validate.notNull(entityDefinition, "entityDefinition"); + this.entityDefinition = entityDefinition; } - public T getItemDefinition() { - return itemDefinition; + public EntityDefinition getEntityDefinition() { + return entityDefinition; } + + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java index 87b9d440739..aa81f7cb374 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -32,9 +32,11 @@ import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -52,6 +54,8 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { ClassDefinitionParser classDefinitionParser = new ClassDefinitionParser(); Map map = new HashMap(); + Map, EntityDefinition> definitionsByClass = new HashMap<>(); + Collection types = ClassMapper.getKnownTypes(); for (RObjectType type : types) { Class clazz = type.getClazz(); @@ -59,13 +63,27 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { continue; } - Definition definition = classDefinitionParser.parseObjectTypeClass(clazz); + EntityDefinition definition = classDefinitionParser.parseObjectTypeClass(clazz); if (definition == null) { continue; } ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(type); - map.put(objectType.getQName(), (EntityDefinition) definition); + map.put(objectType.getTypeQName(), definition); + definitionsByClass.put(definition.getJpaType(), definition); + } + + // link parents (maybe not needed at all, we'll see) + for (EntityDefinition definition : map.values()) { + Class superclass = definition.getJpaType().getSuperclass(); + if (!RObject.class.isAssignableFrom(superclass)) { + continue; + } + EntityDefinition superclassDefinition = definitionsByClass.get(superclass); + if (superclassDefinition == null) { + throw new IllegalStateException("No definition for superclass " + superclass + " of " + definition); + } + definition.setSuperclassDefinition(superclassDefinition); } definitions = Collections.unmodifiableMap(map); @@ -99,11 +117,51 @@ public String debugDump(int indent) { return builder.toString(); } - public D findDefinition(Class type, ItemPath path, Class definitionType) { + public EntityDefinition findEntityDefinition(QName typeName) { + Validate.notNull(typeName, "Type name must not be null."); + + EntityDefinition def = definitions.get(typeName); + if (def == null) { + throw new IllegalStateException("Type " + typeName + " couldn't be found in type registry"); + } + return def; + } + + // always returns non-null value + public EntityDefinition findEntityDefinition(Class type) { Validate.notNull(type, "Type must not be null."); - Validate.notNull(definitionType, "Definition type must not be null."); + return findEntityDefinition(ObjectTypes.getObjectType(type).getTypeQName()); + } - EntityDefinition entityDef = definitions.get(ObjectTypes.getObjectType(type).getQName()); + public DefinitionSearchResult findDefinition(Class type, ItemPath path, Class definitionType) { + Validate.notNull(type, "Type must not be null."); + Validate.notNull(definitionType, "Definition type must not be null."); + EntityDefinition entityDef = findEntityDefinition(type); return entityDef.findDefinition(path, definitionType); } + + /** + * Returns possible "children" of a given definition. + * More abstract classes are listed first. + */ + public List getChildrenOf(EntityDefinition entityDefinition) { + List retval = new ArrayList<>(); + List children = getDirectChildrenOf(entityDefinition); + for (EntityDefinition child : children) { + retval.add(child); + retval.addAll(getChildrenOf(child)); + } + return retval; + } + + private List getDirectChildrenOf(EntityDefinition parentDefinition) { + Class parentClass = parentDefinition.getJpaType(); + List retval = new ArrayList<>(); + for (EntityDefinition definition : definitions.values()) { + if (parentClass.equals(definition.getJpaType().getSuperclass())) { + retval.add(definition); + } + } + return retval; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java index 4c300deb7ae..f98160105b2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java @@ -53,11 +53,6 @@ public RQuery interpret(ObjectQuery query, Class type, QueryInterpreter2 interpreter = new QueryInterpreter2(repoConfiguration); RootHibernateQuery hibernateQuery = interpreter.interpret(query, type, options, prismContext, countingObjects, session); - if (countingObjects) { - hibernateQuery.addProjectionElement(new ProjectionElement("count(*)")); - } else { - hibernateQuery.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); - } return new RQueryImpl(hibernateQuery.getAsHqlQuery(session)); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 2af280db8e8..722aa6f86ec 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.AllFilter; import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.ExistsFilter; import com.evolveum.midpoint.prism.query.InOidFilter; import com.evolveum.midpoint.prism.query.NoneFilter; import com.evolveum.midpoint.prism.query.NotFilter; @@ -41,9 +42,7 @@ import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinitionPath; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -54,8 +53,8 @@ import com.evolveum.midpoint.repo.sql.query2.restriction.AndRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.AnyPropertyRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.CollectionRestriction; +import com.evolveum.midpoint.repo.sql.query2.restriction.ExistsRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.InOidRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.ItemRestrictionOperation; import com.evolveum.midpoint.repo.sql.query2.restriction.NotRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.OrRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.OrgRestriction; @@ -63,12 +62,12 @@ import com.evolveum.midpoint.repo.sql.query2.restriction.ReferenceRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.Restriction; import com.evolveum.midpoint.repo.sql.query2.restriction.TypeRestriction; +import com.evolveum.midpoint.repo.sql.util.GetObjectResult; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import org.apache.commons.lang.Validate; import org.hibernate.Session; @@ -145,12 +144,14 @@ public RootHibernateQuery interpret(ObjectQuery query, Class Restriction findAndCreateRestriction(T filter, LOGGER.trace("Determining restriction for filter {}", filter); - String alias = context.getHibernateQuery().getPrimaryEntityAlias(); + InterpreterHelper helper = context.getHelper(); + EntityDefinition baseEntityDefinition; + if (parent != null) { + baseEntityDefinition = parent.getBaseEntityDefinitionForChildren(); + } else { + baseEntityDefinition = context.getRootEntityDefinition(); + } + Restriction restriction = findAndCreateRestrictionInternal(filter, context, parent, helper, baseEntityDefinition); + LOGGER.trace("Restriction for {} is {}", filter.getClass().getSimpleName(), restriction); + return restriction; + } + + private Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext context, Restriction parent, InterpreterHelper helper, EntityDefinition baseEntityDefinition) throws QueryException { // the order of processing restrictions can be important, so we do the selection via handwritten code - Restriction restriction; + if (filter instanceof AndFilter) { - restriction = new AndRestriction(); + return new AndRestriction(context, (AndFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof OrFilter) { - restriction = new OrRestriction(); + return new OrRestriction(context, (OrFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof NotFilter) { - restriction = new NotRestriction(); + return new NotRestriction(context, (NotFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof InOidFilter) { - restriction = new InOidRestriction(); + return new InOidRestriction(context, (InOidFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof OrgFilter) { - restriction = new OrgRestriction(); + return new OrgRestriction(context, (OrgFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof TypeFilter) { - restriction = new TypeRestriction(); + TypeFilter typeFilter = (TypeFilter) filter; + EntityDefinition refinedEntityDefinition = helper.findRestrictedEntityDefinition(baseEntityDefinition, typeFilter.getType()); + return new TypeRestriction(context, typeFilter, refinedEntityDefinition, parent); + } else if (filter instanceof ExistsFilter) { + ExistsFilter existsFilter = (ExistsFilter) filter; + ItemPath path = existsFilter.getFullPath(); + ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, EntityDefinition.class); + if (searchResult == null) { + throw new QueryException("Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity"); + } + return new ExistsRestriction(context, existsFilter, searchResult.getEntityDefinition(), parent, searchResult.getItemDefinition()); } else if (filter instanceof RefFilter) { - ItemPath fullPath = getFullPath(parent, ((RefFilter) filter).getFullPath()); - EntityDefinition entityDefinition = context.findProperEntityDefinition(fullPath); - restriction = new ReferenceRestriction(entityDefinition, alias, entityDefinition); + RefFilter refFilter = (RefFilter) filter; + ItemPath path = refFilter.getFullPath(); + ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, Definition.class); + if (searchResult == null) { + throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a queryable item"); + } + return new ReferenceRestriction(context, refFilter, searchResult.getEntityDefinition(), + parent, searchResult.getItemDefinition()); } else if (filter instanceof ValueFilter) { ValueFilter valFilter = (ValueFilter) filter; - ItemPath fullPath = getFullPath(parent, valFilter.getFullPath()); + ItemPath path = valFilter.getFullPath(); - ProperDefinitionSearchResult propDef = context.findProperDefinition(fullPath, PropertyDefinition.class); - if (propDef != null && propDef.getItemDefinition() != null) { - restriction = new PropertyRestriction(propDef.getRootEntityDefinition(), alias, propDef.getRootEntityDefinition(), propDef.getItemDefinition()); - } else { - ProperDefinitionSearchResult collDef = context.findProperDefinition(fullPath, CollectionDefinition.class); - if (collDef != null && collDef.getItemDefinition() != null && collDef.getItemDefinition().getDefinition() instanceof PropertyDefinition) { - restriction = new CollectionRestriction(collDef.getRootEntityDefinition(), alias, collDef.getItemDefinition()); + ProperDefinitionSearchResult propDefRes = helper.findProperDefinition(baseEntityDefinition, path, PropertyDefinition.class); + if (propDefRes != null) { + return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getItemDefinition()); + } + ProperDefinitionSearchResult collDefRes = helper.findProperDefinition(baseEntityDefinition, path, CollectionDefinition.class); + if (collDefRes != null) { + Definition innerDef = collDefRes.getItemDefinition().getDefinition(); + if (innerDef instanceof PropertyDefinition) { + return new CollectionRestriction(context, valFilter, collDefRes.getEntityDefinition(), parent, (PropertyDefinition) innerDef); } else { - EntityDefinition entityDefinition = context.findProperEntityDefinition(fullPath); - JpaDefinitionPath jpaDefinitionPath = entityDefinition.translatePath(fullPath); - AnyDefinition anyDefinition = jpaDefinitionPath.getAnyDefinition(); - if (anyDefinition != null) { - restriction = new AnyPropertyRestriction(anyDefinition, entityDefinition, alias, entityDefinition); - } else { - throw new QueryException("Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); - } + throw new QueryException("ValueFilter is not supported for collections of items other than properties: " + innerDef); } } + ProperDefinitionSearchResult anyDefRes = helper.findProperDefinition(baseEntityDefinition, path, AnyDefinition.class); + if (anyDefRes != null) { + if (ItemPath.containsSingleNameSegment(anyDefRes.getRemainder())) { + return new AnyPropertyRestriction(context, valFilter, anyDefRes.getEntityDefinition(), parent, anyDefRes.getItemDefinition()); + } else { + throw new QueryException("Unsupported any-targeted query: should contain single item name to be resolved in the 'any' container but contains '" + + anyDefRes.getRemainder() + "' instead"); + } + } + throw new QueryException("Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); } else if (filter instanceof NoneFilter || filter instanceof AllFilter || filter instanceof UndefinedFilter) { // these should be filtered out by the client throw new IllegalStateException("Trivial filters are not supported by QueryInterpreter: " + filter.debugDump()); } else { throw new IllegalStateException("Unknown filter: " + filter.debugDump()); } - - restriction.setContext(context); - restriction.setParent(parent); - restriction.setFilter(filter); - - LOGGER.trace("Restriction for {} is {}", filter.getClass().getSimpleName(), restriction); - return restriction; } private ItemPath getFullPath(Restriction parent, ItemPath fullPath) { if (parent == null) { return fullPath; } else { - return new ItemPath(parent.getItemPathForChildren(), fullPath); + return new ItemPath(parent.getBaseItemPathForChildren(), fullPath); } } - private void interpretPagingAndSorting(ObjectQuery query, InterpretationContext context, boolean countingObjects) { + private void interpretPagingAndSorting(InterpretationContext context, ObjectQuery query, boolean countingObjects) { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String rootAlias = hibernateQuery.getPrimaryEntityAlias(); @@ -315,7 +333,7 @@ public void updatePagingAndSorting(RootHibernateQuery hib return; } // FIXME this has to be enhanced for multi-segment paths! (e.g. create joins if needed) - Definition def = registry.findDefinition(type, paging.getOrderBy(), Definition.class); + Definition def = registry.findDefinition(type, paging.getOrderBy(), Definition.class).getItemDefinition(); if (def == null) { LOGGER.warn("Unknown path '" + paging.getOrderBy() + "', couldn't find definition for it, " + "list will not be ordered by it."); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java index d88d581e339..8d4b2d2fc6a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java @@ -16,6 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; + import javax.xml.namespace.QName; /** @@ -31,4 +34,13 @@ public AnyDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaTy protected String getDebugDumpClassName() { return "Any"; } + + @Override + public DefinitionSearchResult nextDefinition(ItemPath path) { + // There is nothing we can do here. Return the definition itself, and + // the path as to be found within the appropriate Any container. + // Hoping the client will understand this and won't cycle while finding + // the definition. ;) + return new DefinitionSearchResult(this, path); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 65233fe83ea..442c10dac2d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -125,7 +125,9 @@ private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpa } for (VirtualAny any : qEntity.anyElements()) { - VirtualAnyDefinition def = new VirtualAnyDefinition(new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart())); + VirtualAnyDefinition def = new VirtualAnyDefinition( + new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()), + any.ownerType()); entityDef.addDefinition(def); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java index 6a0fdc4e87e..99d04f6a149 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.query2.definition; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.Holder; @@ -42,8 +43,8 @@ void setDefinition(Definition definition) { } @Override - public Definition nextDefinition(Holder pathHolder) { - return definition; + public DefinitionSearchResult nextDefinition(ItemPath path) { + return new DefinitionSearchResult(definition, path); } @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java index b989b17498f..6aab7313421 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java @@ -17,9 +17,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.Holder; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -122,66 +122,83 @@ public String debugDump(int indent) { * Parts of the path that have no representation in the repository (e.g. metadata, * construction) are simply skipped. * - * On return, ItemPath (pathHolder) contains the remainder that is to be resolved. - * - * @param pathHolder - * @param + * @param path A path to be resolved. Always non-null and non-empty. * @return + * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain + * and the unresolved remainder of the path. + * - If the search was not successful, returns null. + * - Note that for "Any" container returns the container entity definition itself plus the path that is to + * be searched in the given "Any" container. However, there's no point in repeating the search there, + * as it would yield the same result. */ - public Definition nextDefinition(Holder pathHolder) { - return null; - } - - // beware, path translation can end e.g. in ANY element (extension, attributes) - // also, beware of parent links and cross-entity links - public JpaDefinitionPath translatePath(ItemPath path) { - Holder pathHolder = new Holder<>(path); - JpaDefinitionPath jpaPath = new JpaDefinitionPath(); - - Definition currentDefinition = this; - for (;;) { - ItemPath currentPath = pathHolder.getValue(); - if (currentDefinition == null || currentPath == null || currentPath.isEmpty()) { - LOGGER.trace("ItemPath {} translated to JpaDefinitionPath {}; remainder {} (started in {})", path, jpaPath, currentPath, this.getShortInfo()); - return jpaPath; - } - ItemPath origPath = pathHolder.getValue(); - currentDefinition = currentDefinition.nextDefinition(pathHolder); - LOGGER.trace("nextDefinition on {} returned {}", origPath, currentDefinition != null ? currentDefinition.getShortInfo() : "(null)"); - if (currentDefinition != null) { - jpaPath.add(currentDefinition); - } - } - } + public abstract DefinitionSearchResult nextDefinition(ItemPath path); /** * Resolves the whole ItemPath. + * + * If successful, returns either: + * - correct definition + empty path, or + * - Any definition + path remainder + * + * If unsuccessful, return null. + * * @return */ - public D findDefinition(ItemPath path, Class type) { - Holder pathHolder = new Holder<>(path); + public DefinitionSearchResult findDefinition(ItemPath path, Class type) { Definition currentDefinition = this; for (;;) { - ItemPath currentPath = pathHolder.getValue(); - if (currentPath == null || currentPath.isEmpty()) { + if (ItemPath.isNullOrEmpty(path)) { // we are at the end of search - hoping we found the correct class if (type.isAssignableFrom(currentDefinition.getClass())) { - return (D) currentDefinition; + return new DefinitionSearchResult<>((D) currentDefinition, null); } else { return null; } } - if (currentDefinition instanceof AnyDefinition && type.isAssignableFrom(AnyDefinition.class)) { - return (D) currentDefinition; + if (currentDefinition instanceof AnyDefinition) { + if (type.isAssignableFrom(AnyDefinition.class)) { + return new DefinitionSearchResult<>((D) currentDefinition, path); + } else { + return null; + } } - currentDefinition = currentDefinition.nextDefinition(pathHolder); - if (currentDefinition == null) { + DefinitionSearchResult result = currentDefinition.nextDefinition(path); + if (result == null) { // oops return null; } + currentDefinition = result.getItemDefinition(); + path = result.getRemainder(); } } - public D findDefinition(QName jaxbName, Class type) { - return null; + /** + * Translates ItemPath to a sequence of definitions. + * + * @param itemPath + * @return The translation (if successful) or null (if not successful). + * For "Any" elements, the last element in the path is Any. + * + * Note: structurally similar to findDefinition above + */ + + public DefinitionPath translatePath(ItemPath itemPath) { + Definition currentDefinition = this; + ItemPath originalPath = itemPath; // we remember original path just for logging + DefinitionPath definitionPath = new DefinitionPath(); + + for (;;) { + if (currentDefinition instanceof AnyDefinition || ItemPath.isNullOrEmpty(itemPath)) { + LOGGER.trace("ItemPath {} translated to DefinitionPath {} (started in {})", originalPath, definitionPath, this.getShortInfo()); + return definitionPath; + } + DefinitionSearchResult result = currentDefinition.nextDefinition(itemPath); + LOGGER.trace("nextDefinition on {} returned {}", itemPath, result != null ? result.getItemDefinition().getShortInfo() : "(null)"); + if (result == null) { + return null; // sorry we failed + } + currentDefinition = result.getItemDefinition(); + definitionPath.add(currentDefinition); + itemPath = result.getRemainder(); + } } public String getShortInfo() { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java similarity index 98% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java index e426df5a368..28d16d7c40e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinitionPath.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java @@ -24,7 +24,7 @@ * * @author mederly */ -public class JpaDefinitionPath { +public class DefinitionPath { private List definitions = new ArrayList<>(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java index f663dc7ac31..87f54440ccf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.repo.sql.query.restriction.PathTranslation; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.Holder; import com.evolveum.midpoint.util.QNameUtil; @@ -28,6 +29,7 @@ import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -42,9 +44,14 @@ public class EntityDefinition extends Definition { */ private List definitions; private boolean embedded; + private EntityDefinition superclassDefinition; public EntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { super(jaxbName, jaxbType, jpaName, jpaType); + Validate.notNull(jaxbName, "jaxbName"); + Validate.notNull(jaxbType, "jaxbType"); + Validate.notNull(jpaName, "jpaName"); + Validate.notNull(jpaType, "jpaType"); } public boolean isEmbedded() { @@ -112,9 +119,7 @@ protected String getDebugDumpClassName() { return "Ent"; } - - @Override - public D findDefinition(QName jaxbName, Class type) { + private D findDefinition(QName jaxbName, Class type) { Validate.notNull(jaxbName, "Jaxb name must not be null."); Validate.notNull(type, "Definition type must not be null."); @@ -131,39 +136,68 @@ public D findDefinition(QName jaxbName, Class type) { } @Override - public Definition nextDefinition(Holder pathHolder) { - ItemPath path = pathHolder.getValue(); + public DefinitionSearchResult nextDefinition(ItemPath path) { - for (;;) { - if (path == null || path.isEmpty()) { - return this; // in some cases (metadata, construction) this return value might be suspicious, or altogether wrong -- but we don't care - } + // first treat known discrepancies betweeen prism structure and repo representation: + // metadata -> none, + // construction/resourceRef -> resourceRef + while (skipFirstItem(path)) { + path = path.tail(); + } - NameItemPathSegment first = (NameItemPathSegment) path.first(); - QName firstName = first.getName(); + // now find the definition + if (ItemPath.isNullOrEmpty(path)) { + // note that for wrong input (e.g. path=metadata) this answer might be wrong, but we don't care + return new DefinitionSearchResult(this, null); + } - path = path.tail(); - pathHolder.setValue(path); + QName firstName = ((NameItemPathSegment) path.first()).getName(); + Definition def = findDefinition(firstName, Definition.class); + if (def != null) { + return new DefinitionSearchResult(def, path.tail()); + } else { + return null; + } + } - // just a lookahead - QName secondName = null; - if (!path.isEmpty() && path.first() instanceof NameItemPathSegment) { - NameItemPathSegment second = ((NameItemPathSegment) (path.first())); - secondName = second.getName(); - } + private boolean skipFirstItem(ItemPath path) { + if (ItemPath.isNullOrEmpty(path)) { + return false; + } + QName firstName = ((NameItemPathSegment) path.first()).getName(); - // known discrepancies betweeen prism structure and repo representation - if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { - continue; // metadata is not an repository entity - } - if (QNameUtil.match(firstName, AssignmentType.F_CONSTRUCTION) && - QNameUtil.match(secondName, ConstructionType.F_RESOURCE_REF)) { - continue; // construction/resourceRef -> resourceRef - } + // metadata -> null + if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { + return true; + } - Definition def = findDefinition(firstName, Definition.class); - return def; + // construction/resourceRef -> construction + ItemPath remainder = path.tail(); + if (remainder.isEmpty() || !(remainder.first() instanceof NameItemPathSegment)) { + return false; } + NameItemPathSegment second = ((NameItemPathSegment) (remainder.first())); + QName secondName = second.getName(); + if (QNameUtil.match(firstName, AssignmentType.F_CONSTRUCTION) && + QNameUtil.match(secondName, ConstructionType.F_RESOURCE_REF)) { + return true; + } + return false; + } + + public boolean isAssignableFrom(EntityDefinition specificEntityDefinition) { + return getJpaType().isAssignableFrom(specificEntityDefinition.getJpaType()); } + public boolean isAbstract() { + return Modifier.isAbstract(getJpaType().getModifiers()); + } + + public void setSuperclassDefinition(EntityDefinition superclassDefinition) { + this.superclassDefinition = superclassDefinition; + } + + public EntityDefinition getSuperclassDefinition() { + return superclassDefinition; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java index c1c9c085ca1..4c1661d1a32 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java @@ -17,17 +17,17 @@ package com.evolveum.midpoint.repo.sql.query.restriction; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinitionPath; +import com.evolveum.midpoint.repo.sql.query2.definition.DefinitionPath; /** * @author Pavol */ public class PathTranslation { - private JpaDefinitionPath jpaDefinitionPath; + private DefinitionPath definitionPath; private ItemPath itemPathRemainder; - public PathTranslation(JpaDefinitionPath jpaDefinitionPath, ItemPath itemPathRemainder) { - this.jpaDefinitionPath = jpaDefinitionPath; + public PathTranslation(DefinitionPath definitionPath, ItemPath itemPathRemainder) { + this.definitionPath = definitionPath; this.itemPathRemainder = itemPathRemainder; } @@ -35,8 +35,8 @@ public boolean isComplete() { return ItemPath.isNullOrEmpty(itemPathRemainder); } - public JpaDefinitionPath getJpaDefinitionPath() { - return jpaDefinitionPath; + public DefinitionPath getDefinitionPath() { + return definitionPath; } public ItemPath getItemPathRemainder() { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java index 3f069afff6a..f69255fe7ff 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java @@ -16,7 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import javax.xml.namespace.QName; @@ -74,4 +76,10 @@ protected void toStringExtended(StringBuilder builder) { protected String getDebugDumpClassName() { return "Prop"; } + + @Override + public DefinitionSearchResult nextDefinition(ItemPath path) { + // nowhere to come from here + return null; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java index f987ade55ec..c3bc89b04db 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java @@ -16,6 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; + import javax.xml.namespace.QName; /** @@ -46,4 +49,10 @@ protected void toStringExtended(StringBuilder builder) { protected String getDebugDumpClassName() { return "Ref"; } + + @Override + public DefinitionSearchResult nextDefinition(ItemPath path) { + // nowhere to come from here + return null; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java index cca265f9de0..f3998685d6c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java @@ -16,6 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import org.apache.commons.lang.Validate; + import javax.xml.namespace.QName; /** @@ -23,7 +26,15 @@ */ public class VirtualAnyDefinition extends AnyDefinition { - public VirtualAnyDefinition(QName jaxbName) { + private RObjectExtensionType ownerType; // ObjectType (for extension) or ShadowType (for attributes) + + public VirtualAnyDefinition(QName jaxbName, RObjectExtensionType ownerType) { super(jaxbName, null, null, null); + Validate.notNull(ownerType, "ownerType"); + this.ownerType = ownerType; + } + + public RObjectExtensionType getOwnerType() { + return ownerType; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index a0c8663fa53..1050b444442 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -204,7 +204,7 @@ public void setOrder(String propertyPath, OrderDirection direction) { public abstract RootHibernateQuery getRootQuery(); - // used to narrow the primary entity e.g. from RObject to RUser (e.g. during ItemRestriction processing) + // used to narrow the primary entity e.g. from RObject to RUser (e.g. during ItemValueRestriction processing) public void narrowPrimaryEntity(EntityDefinition newDefinition) throws QueryException { String oldEntityName = getPrimaryEntity().getName(); Class oldEntityClass = ClassMapper.getHqlClassForHqlName(oldEntityName); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java index c46151a1365..9d0649921dd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -30,6 +31,10 @@ */ public class AndRestriction extends NaryLogicalRestriction { + public AndRestriction(InterpretationContext context, AndFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + @Override public Condition interpret() throws QueryException { validateFilter(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index 43678540cbf..79a57c7cf65 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -18,7 +18,6 @@ import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.ValueFilter; @@ -26,35 +25,31 @@ import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Restrictions; import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.List; /** * @author lazyman */ -public class AnyPropertyRestriction extends ItemRestriction { +public class AnyPropertyRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(AnyPropertyRestriction.class); private AnyDefinition anyDefinition; - public AnyPropertyRestriction(AnyDefinition anyDefinition, EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { - super(rootEntityDefinition, startPropertyPath, startEntityDefinition); + public AnyPropertyRestriction(InterpretationContext context, ValueFilter filter, EntityDefinition baseEntityDefinition, + Restriction parent, AnyDefinition anyDefinition) { + super(context, filter, baseEntityDefinition, parent); Validate.notNull(anyDefinition, "anyDefinition"); this.anyDefinition = anyDefinition; } @@ -70,22 +65,19 @@ public Condition interpretInternal(String hqlPath) throws QueryException { throw new QueryException("Couldn't get name or type for queried item '" + itemDefinition + "'"); } - ItemPath fullPath = getFullPath(filter.getFullPath()); // TODO does not work for cross-entities! - RObjectExtensionType ownerType; if (anyDefinition instanceof VirtualAnyDefinition) { - ownerType = fullPath.first().equivalent(new NameItemPathSegment(ObjectType.F_EXTENSION)) ? - RObjectExtensionType.EXTENSION : RObjectExtensionType.ATTRIBUTES; // TODO write more nicely (e.g. using VirtualAnyDefinition field) + ownerType = ((VirtualAnyDefinition) anyDefinition).getOwnerType(); } else { ownerType = null; // assignment extension has no ownerType } - String anyAssociationName = null; // longs, strings, ... + String anyAssociationName; // longs, strings, ... try { anyAssociationName = RAnyConverter.getAnySetType(itemDefinition); } catch (SchemaException e) { throw new QueryException(e.getMessage(), e); } - String alias = addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); + String alias = getHelper().addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); String propertyValuePath = alias + '.' + RAnyValue.F_VALUE; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java index 50bd19602b1..03f3724267b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java @@ -16,11 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; @@ -30,20 +28,21 @@ /** * @author lazyman */ -public class CollectionRestriction extends ItemRestriction { +public class CollectionRestriction extends ItemValueRestriction { - private CollectionDefinition collectionDefinition; + private PropertyDefinition collectionPropertyDefinition; - public CollectionRestriction(EntityDefinition rootEntityDefinition, String alias, CollectionDefinition collectionDefinition) { - super(rootEntityDefinition, alias, rootEntityDefinition); - Validate.notNull(collectionDefinition); - this.collectionDefinition = collectionDefinition; + public CollectionRestriction(InterpretationContext context, ValueFilter filter, EntityDefinition baseEntityDefinition, + Restriction parent, PropertyDefinition collectionPropertyDefinition) { + super(context, filter, baseEntityDefinition, parent); + Validate.notNull(collectionPropertyDefinition, "collectionPropertyDefinition"); + this.collectionPropertyDefinition = collectionPropertyDefinition; } @Override public Condition interpretInternal(String hqlPath) throws QueryException { - Object value = getValueFromFilter(filter, (PropertyDefinition) collectionDefinition.getDefinition()); + Object value = getValueFromFilter(filter, collectionPropertyDefinition); return createCondition(hqlPath, value, filter); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java new file mode 100644 index 00000000000..b15967612a0 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ExistsFilter; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class ExistsRestriction extends ItemRestriction { + + /** + * Definition of the entity when this restriction starts. It is usually the same as rootEntityDefinition, + * but for Exists children it is the entity pointed to by Exists restriction. + * + * TODO think out the process of refinement of entity definition e.g. RObject->RUser + */ + private EntityDefinition baseEntityDefinitionForChildren; + + /** + * HQL path to be used for child restrictions. + */ + private String baseHqlPathForChildren; + + public ExistsRestriction(InterpretationContext context, ExistsFilter filter, EntityDefinition baseEntityDefinition, + Restriction parent, EntityDefinition baseEntityDefinitionForChildren) { + super(context, filter, baseEntityDefinition, parent); + Validate.notNull(baseEntityDefinitionForChildren, "baseEntityDefinitionForChildren"); + this.baseEntityDefinitionForChildren = baseEntityDefinitionForChildren; + } + + @Override + public Condition interpret() throws QueryException { + baseHqlPathForChildren = getHelper().prepareJoins(filter.getFullPath(), parent.getBaseHqlPathForChildren(), baseEntityDefinition); + + InterpretationContext context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + return interpreter.interpretFilter(context, filter.getFilter(), this); + } + + @Override + public String getBaseHqlPathForChildren() { + return baseHqlPathForChildren; + } + + @Override + public ItemPath getBaseItemPathForChildren() { + return new ItemPath(getBaseItemPath(), filter.getFullPath()); + } + + @Override + public EntityDefinition getBaseEntityDefinitionForChildren() { + return baseEntityDefinitionForChildren; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java index 81656e1e65c..9961a87d622 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java @@ -16,22 +16,24 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.InOidFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; /** * @author lazyman */ public class InOidRestriction extends Restriction { + public InOidRestriction(InterpretationContext context, InOidFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + @Override public Condition interpret() throws QueryException { - return getContext().getHibernateQuery().createIn(context.getCurrentHqlPropertyPath() + ".oid", filter.getOids()); + return getContext().getHibernateQuery().createIn(getBaseHqlPath() + ".oid", filter.getOids()); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index 3bef60f6759..db156d2985f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -16,380 +16,17 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.GreaterFilter; -import com.evolveum.midpoint.prism.query.LessFilter; -import com.evolveum.midpoint.prism.query.PropertyValueFilter; -import com.evolveum.midpoint.prism.query.SubstringFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; -import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; -import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; -import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinitionPath; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; -import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; -import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; -import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; -import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; -import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; -import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.apache.commons.lang.Validate; - -import javax.xml.namespace.QName; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; /** - * Abstract superclass for all value-related filters. There are two major problems solved: - * 1) mapping from ItemPath to HQL property paths - * 2) adding joined entities to the query, along with necessary conditions - * (there are two kinds of joins: left outer join and carthesian join) - * - * After the necessary entity is available, the fine work (creating one or more conditions - * to execute the filtering) is done by subclasses of this path in the interpretInternal(..) method. - * - * @author lazyman * @author mederly */ -public abstract class ItemRestriction extends Restriction { - - private static final Trace LOGGER = TraceManager.getTrace(ItemRestriction.class); - - /** - * Definition of the root entity. Root entity corresponds to the ObjectType class that was requested - * by the search operation, or the one that was refined from abstract types (ObjectType, AbstractRoleType, ...) - * in the process of restriction construction. - */ - private EntityDefinition rootEntityDefinition; - - /** - * Property path that is the base of this restriction. - * - * For simple cases like UserType: name, UserType: activation/administrativeStatus etc. the root - * is the query primary entity alias (e.g. u in "RUser u"). - * - * For "ForValue" filters the startPropertyPath corresponds to the base item pointed to by the filter. - * E.g. in "UserType: ForValue (assignment)" it is "a" (provided that there is - * "RUser u left join u.assignments a with ..." already defined). - * - * (Item restriction expects that its root is already defined in the FROM clause.) - */ - private String startPropertyPath; - - /** - * Definition of the entity when this restriction starts. It is usually the same as rootEntityDefinition, - * but for ForValue children it is the entity pointed to by ForValue restriction. (I.e. assignment in the above - * example.) - */ - private EntityDefinition startEntityDefinition; - - public ItemRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { - Validate.notNull(rootEntityDefinition); - Validate.notNull(startPropertyPath); - Validate.notNull(startEntityDefinition); - this.rootEntityDefinition = rootEntityDefinition; - this.startPropertyPath = startPropertyPath; - this.startEntityDefinition = startEntityDefinition; - } - - @Override - public Condition interpret() throws QueryException { - - ItemPath path = filter.getFullPath(); - if (ItemPath.isNullOrEmpty(path)) { - throw new QueryException("Null or empty path for ItemRestriction in " + filter.debugDump()); - } - - String hqlPropertyPath = prepareJoins(path); - - Condition condition = interpretInternal(hqlPropertyPath); - return condition; - } - - // returns property path that can be used to access the item values - private String prepareJoins(ItemPath relativePath) throws QueryException { - - ItemPath fullPath = getFullPath(relativePath); - LOGGER.trace("Updating query context based on path {}; full path is {}", relativePath, fullPath); - - /** - * We have to do something like this - examples: - * - activation.administrativeStatus -> (nothing, activation is embedded entity) - * - assignment.targetRef -> "left join u.assignments a with ..." - * - assignment.resourceRef -> "left join u.assignments a with ..." - * - organization -> "left join u.organization o" - * - * Or more complex: - * - assignment.modifyApproverRef -> "left join u.assignments a (...) left join a.modifyApproverRef m (...)" - * - assignment.target.longs -> "left join u.assignments a (...), RObject o left join o.longs (...)" - */ - JpaDefinitionPath jpaDefinitionPath = startEntityDefinition.translatePath(relativePath); - String currentHqlPath = startPropertyPath; - - List definitions = jpaDefinitionPath.getDefinitions(); - for (int i = 0; i < definitions.size(); i++) { - Definition definition = definitions.get(i); - if (definition instanceof EntityDefinition) { - EntityDefinition entityDef = (EntityDefinition) definition; - if (!entityDef.isEmbedded()) { - LOGGER.trace("Adding join for '{}' to context", entityDef.getJpaName()); - currentHqlPath = addJoin(entityDef, currentHqlPath); - } else { - currentHqlPath += "." + entityDef.getJpaName(); - } - } else if (definition instanceof AnyDefinition) { - if (definition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes - LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); - currentHqlPath = addJoin(definition, currentHqlPath); - } - break; - } else if (definition instanceof CollectionDefinition) { - LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); - currentHqlPath = addJoin(definition, currentHqlPath); - - // Because the next definition in the chain is the one that is referred to by this Collection - // (either property, reference or entity), we need to skip it: If it's entity, we have already - // joined it - and if it's property/reference, we would break the cycle even so - i++; - - } else if (definition instanceof PropertyDefinition || definition instanceof ReferenceDefinition) { - break; // quite redundant, as this is the last item in the chain - } else { - throw new QueryException("Not implemented yet: " + definition); - } - // TODO entity crossjoin references (when crossing object boundaries) - } - - LOGGER.trace("prepareJoins({}) returning currentHqlPath of {}", relativePath, currentHqlPath); - return currentHqlPath; - } - - protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) throws QueryException { - RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) - String joinedItemJpaName = joinedItemDefinition.getJpaName(); - String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); - Condition condition = null; - if (joinedItemDefinition instanceof VirtualCollectionDefinition) { - VirtualCollectionDefinition vcd = (VirtualCollectionDefinition) joinedItemDefinition; - List conditions = new ArrayList<>(vcd.getAdditionalParams().length); - for (VirtualQueryParam vqp : vcd.getAdditionalParams()) { - // e.g. name = "assignmentOwner", type = RAssignmentOwner.class, value = "ABSTRACT_ROLE" - Object value = createQueryParamValue(vqp); - Condition c = hibernateQuery.createEq(joinedItemAlias + "." + vqp.name(), value); - conditions.add(c); - } - if (conditions.size() > 1) { - condition = hibernateQuery.createAnd(conditions); - } else if (conditions.size() == 1) { - condition = conditions.iterator().next(); - } - } - entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); - return joinedItemAlias; - } - - /** - * This method provides transformation from {@link String} value defined in - * {@link com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam#value()} to real object. Currently only - * to simple types and enum values. - */ - private Object createQueryParamValue(VirtualQueryParam param) throws QueryException { - Class type = param.type(); - String value = param.value(); - - try { - if (type.isPrimitive()) { - return type.getMethod("valueOf", new Class[]{String.class}).invoke(null, new Object[]{value}); - } - - if (type.isEnum()) { - return Enum.valueOf(type, value); - } - } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException|RuntimeException ex) { - throw new QueryException("Couldn't transform virtual query parameter '" - + param.name() + "' from String to '" + type + "', reason: " + ex.getMessage(), ex); - } - - throw new QueryException("Couldn't transform virtual query parameter '" - + param.name() + "' from String to '" + type + "', it's not yet implemented."); - } +public abstract class ItemRestriction extends Restriction { - - protected String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { - RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) - String joinedItemJpaName = anyAssociationName; - String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); - - AndCondition conjunction = hibernateQuery.createAnd(); - if (ownerType != null) { // null for assignment extensions - conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType)); - } - conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); - - entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); - return joinedItemAlias; - } - - public abstract Condition interpretInternal(String hqlPath) throws QueryException; - - protected Condition createCondition(String propertyName, Object value, ValueFilter filter) throws QueryException { - ItemRestrictionOperation operation; - if (filter instanceof EqualFilter) { - operation = ItemRestrictionOperation.EQ; - } else if (filter instanceof GreaterFilter) { - GreaterFilter gf = (GreaterFilter) filter; - operation = gf.isEquals() ? ItemRestrictionOperation.GE : ItemRestrictionOperation.GT; - } else if (filter instanceof LessFilter) { - LessFilter lf = (LessFilter) filter; - operation = lf.isEquals() ? ItemRestrictionOperation.LE : ItemRestrictionOperation.LT; - } else if (filter instanceof SubstringFilter) { - SubstringFilter substring = (SubstringFilter) filter; - if (substring.isAnchorEnd()) { - operation = ItemRestrictionOperation.ENDS_WITH; - } else if (substring.isAnchorStart()) { - operation = ItemRestrictionOperation.STARTS_WITH; - } else { - operation = ItemRestrictionOperation.SUBSTRING; - } - } else { - throw new QueryException("Can't translate filter '" + filter + "' to operation."); - } - - InterpretationContext context = getContext(); - QueryInterpreter2 interpreter = context.getInterpreter(); - Matcher matcher = interpreter.findMatcher(value); - - String matchingRule = null; - if (filter.getMatchingRule() != null){ - matchingRule = filter.getMatchingRule().getLocalPart(); - } - - return matcher.match(context.getHibernateQuery(), operation, propertyName, value, matchingRule); + public ItemRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); } - - protected Object getValue(List values) { - if (values == null || values.isEmpty()) { - return null; - } - - PrismValue val = values.get(0); - if (val instanceof PrismPropertyValue) { - PrismPropertyValue propertyValue = (PrismPropertyValue) val; - return propertyValue.getValue(); - } - - return null; - } - - protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) throws QueryException { - Object value; - if (filter instanceof PropertyValueFilter) { - value = getValue(((PropertyValueFilter) filter).getValues()); - } else { - throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); - } - - //todo remove after some time [lazyman] - //attempt to fix value type for polystring (if it was string in filter we create polystring from it) - if (PolyString.class.equals(def.getJaxbType()) && (value instanceof String)) { - LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", new Object[]{filter}); - value = new PolyString((String) value, (String) value); - } - //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) - if (PolyString.class.equals(def.getJaxbType()) && (value instanceof PolyStringType)) { - LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", new Object[]{filter}); - PolyStringType type = (PolyStringType) value; - value = new PolyString(type.getOrig(), type.getNorm()); - } - - if (String.class.equals(def.getJaxbType()) && (value instanceof QName)) { - //eg. shadow/objectClass - value = RUtil.qnameToString((QName) value); - } - - if (value != null && !def.getJaxbType().isAssignableFrom(value.getClass())) { - throw new QueryException("Value should be type of '" + def.getJaxbType() + "' but it's '" - + value.getClass() + "', filter '" + filter + "'."); - } - - if (def.isEnumerated()) { - value = getRepoEnumValue((Enum) value, def.getJpaType()); - } - - return value; - } - - private Enum getRepoEnumValue(Enum schemaValue, Class repoType) throws QueryException { - if (schemaValue == null) { - return null; - } - - if (SchemaEnum.class.isAssignableFrom(repoType)) { - return (Enum) RUtil.getRepoEnumValue(schemaValue, repoType); - } - - Object[] constants = repoType.getEnumConstants(); - for (Object constant : constants) { - Enum e = (Enum) constant; - if (e.name().equals(schemaValue.name())) { - return e; - } - } - - throw new QueryException("Unknown enum value '" + schemaValue + "', which is type of '" - + schemaValue.getClass() + "'."); - } - - - - /** - * Filter of type NOT(PROPERTY=VALUE) causes problems when there are entities with PROPERTY set to NULL. - * - * Such a filter has to be treated like - * - * NOT (PROPERTY=VALUE & PROPERTY IS NOT NULL) - * - * TODO implement for restrictions other than PropertyRestriction. - */ - protected Condition addIsNotNullIfNecessary(Condition condition, String propertyPath) { - if (condition instanceof IsNullCondition || condition instanceof IsNotNullCondition) { - return condition; - } - if (!isNegated()) { - return condition; - } - RootHibernateQuery hibernateQuery = getContext().getHibernateQuery(); - AndCondition conjunction = hibernateQuery.createAnd(); - conjunction.add(condition); - conjunction.add(hibernateQuery.createIsNotNull(propertyPath)); - return conjunction; - } - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java new file mode 100644 index 00000000000..3df6ba38d1e --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.restriction; + +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.EqualFilter; +import com.evolveum.midpoint.prism.query.GreaterFilter; +import com.evolveum.midpoint.prism.query.LessFilter; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; +import com.evolveum.midpoint.prism.query.SubstringFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; +import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + +import javax.xml.namespace.QName; +import java.util.List; + +/** + * Abstract superclass for all value-related filters. There are two major problems solved: + * 1) mapping from ItemPath to HQL property paths + * 2) adding joined entities to the query, along with necessary conditions + * (there are two kinds of joins: left outer join and carthesian join) + * + * After the necessary entity is available, the fine work (creating one or more conditions + * to execute the filtering) is done by subclasses of this path in the interpretInternal(..) method. + * + * @author lazyman + * @author mederly + */ +public abstract class ItemValueRestriction extends ItemRestriction { + + private static final Trace LOGGER = TraceManager.getTrace(ItemValueRestriction.class); + + public ItemValueRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + + @Override + public Condition interpret() throws QueryException { + + ItemPath path = filter.getFullPath(); + if (ItemPath.isNullOrEmpty(path)) { + throw new QueryException("Null or empty path for ItemValueRestriction in " + filter.debugDump()); + } + String hqlPropertyPath = getHelper().prepareJoins(path, getBaseHqlPath(), baseEntityDefinition); + + Condition condition = interpretInternal(hqlPropertyPath); + return condition; + } + + public abstract Condition interpretInternal(String hqlPath) throws QueryException; + + protected Condition createCondition(String propertyName, Object value, ValueFilter filter) throws QueryException { + ItemRestrictionOperation operation; + if (filter instanceof EqualFilter) { + operation = ItemRestrictionOperation.EQ; + } else if (filter instanceof GreaterFilter) { + GreaterFilter gf = (GreaterFilter) filter; + operation = gf.isEquals() ? ItemRestrictionOperation.GE : ItemRestrictionOperation.GT; + } else if (filter instanceof LessFilter) { + LessFilter lf = (LessFilter) filter; + operation = lf.isEquals() ? ItemRestrictionOperation.LE : ItemRestrictionOperation.LT; + } else if (filter instanceof SubstringFilter) { + SubstringFilter substring = (SubstringFilter) filter; + if (substring.isAnchorEnd()) { + operation = ItemRestrictionOperation.ENDS_WITH; + } else if (substring.isAnchorStart()) { + operation = ItemRestrictionOperation.STARTS_WITH; + } else { + operation = ItemRestrictionOperation.SUBSTRING; + } + } else { + throw new QueryException("Can't translate filter '" + filter + "' to operation."); + } + + InterpretationContext context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + Matcher matcher = interpreter.findMatcher(value); + + String matchingRule = null; + if (filter.getMatchingRule() != null){ + matchingRule = filter.getMatchingRule().getLocalPart(); + } + + return matcher.match(context.getHibernateQuery(), operation, propertyName, value, matchingRule); + } + + protected Object getValue(List values) { + if (values == null || values.isEmpty()) { + return null; + } + + PrismValue val = values.get(0); + if (val instanceof PrismPropertyValue) { + PrismPropertyValue propertyValue = (PrismPropertyValue) val; + return propertyValue.getValue(); + } + + return null; + } + + protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) throws QueryException { + Object value; + if (filter instanceof PropertyValueFilter) { + value = getValue(((PropertyValueFilter) filter).getValues()); + } else { + throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); + } + + //todo remove after some time [lazyman] + //attempt to fix value type for polystring (if it was string in filter we create polystring from it) + if (PolyString.class.equals(def.getJaxbType()) && (value instanceof String)) { + LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", new Object[]{filter}); + value = new PolyString((String) value, (String) value); + } + //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) + if (PolyString.class.equals(def.getJaxbType()) && (value instanceof PolyStringType)) { + LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", new Object[]{filter}); + PolyStringType type = (PolyStringType) value; + value = new PolyString(type.getOrig(), type.getNorm()); + } + + if (String.class.equals(def.getJaxbType()) && (value instanceof QName)) { + //eg. shadow/objectClass + value = RUtil.qnameToString((QName) value); + } + + if (value != null && !def.getJaxbType().isAssignableFrom(value.getClass())) { + throw new QueryException("Value should be type of '" + def.getJaxbType() + "' but it's '" + + value.getClass() + "', filter '" + filter + "'."); + } + + if (def.isEnumerated()) { + value = getRepoEnumValue((Enum) value, def.getJpaType()); + } + + return value; + } + + private Enum getRepoEnumValue(Enum schemaValue, Class repoType) throws QueryException { + if (schemaValue == null) { + return null; + } + + if (SchemaEnum.class.isAssignableFrom(repoType)) { + return (Enum) RUtil.getRepoEnumValue(schemaValue, repoType); + } + + Object[] constants = repoType.getEnumConstants(); + for (Object constant : constants) { + Enum e = (Enum) constant; + if (e.name().equals(schemaValue.name())) { + return e; + } + } + + throw new QueryException("Unknown enum value '" + schemaValue + "', which is type of '" + + schemaValue.getClass() + "'."); + } + + + + /** + * Filter of type NOT(PROPERTY=VALUE) causes problems when there are entities with PROPERTY set to NULL. + * + * Such a filter has to be treated like + * + * NOT (PROPERTY=VALUE & PROPERTY IS NOT NULL) + * + * TODO implement for restrictions other than PropertyRestriction. + */ + protected Condition addIsNotNullIfNecessary(Condition condition, String propertyPath) { + if (condition instanceof IsNullCondition || condition instanceof IsNotNullCondition) { + return condition; + } + if (!isNegated()) { + return condition; + } + RootHibernateQuery hibernateQuery = getContext().getHibernateQuery(); + AndCondition conjunction = hibernateQuery.createAnd(); + conjunction.add(condition); + conjunction.add(hibernateQuery.createIsNotNull(propertyPath)); + return conjunction; + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java index f55b6018f03..e4da5d89081 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java @@ -17,10 +17,15 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; import com.evolveum.midpoint.prism.query.LogicalFilter; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; /** * @author lazyman */ public abstract class LogicalRestriction extends Restriction { + public LogicalRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java index 832273b9543..a6470ce20a9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java @@ -16,12 +16,12 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NaryLogicalFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.JunctionCondition; import com.evolveum.midpoint.util.logging.Trace; @@ -38,6 +38,10 @@ public abstract class NaryLogicalRestriction extend private static final Trace LOGGER = TraceManager.getTrace(NaryLogicalRestriction.class); private List restrictions; + public NaryLogicalRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + public List getRestrictions() { if (restrictions == null) { restrictions = new ArrayList<>(); @@ -60,7 +64,7 @@ protected void updateJunction(List subfilters, JunctionC QueryInterpreter2 interpreter = context.getInterpreter(); for (ObjectFilter subfilter : subfilters) { - Condition condition = interpreter.interpretFilter(subfilter, context, this); + Condition condition = interpreter.interpretFilter(context, subfilter, this); junction.add(condition); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java index a6b120bb964..e46202edb4e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.NotCondition; @@ -29,6 +30,10 @@ */ public class NotRestriction extends UnaryLogicalRestriction { + public NotRestriction(InterpretationContext context, NotFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + @Override public Condition interpret() throws QueryException { validateFilter(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java index 84bbf908659..e638215c7ce 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java @@ -16,10 +16,10 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; @@ -29,6 +29,10 @@ */ public class OrRestriction extends NaryLogicalRestriction { + public OrRestriction(InterpretationContext context, OrFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + @Override public Condition interpret() throws QueryException { validateFilter(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java index 15627b08479..89eec446097 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -16,32 +16,29 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.OrgFilter; import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.hqm.QueryParameterValue; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; -import org.hibernate.Query; - -import java.util.HashMap; -import java.util.Map; /** * @author lazyman */ public class OrgRestriction extends Restriction { + public OrgRestriction(InterpretationContext context, OrgFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + @Override public Condition interpret() throws QueryException { RootHibernateQuery hibernateQuery = getContext().getHibernateQuery(); if (filter.isRoot()) { // oid in (select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1) - return hibernateQuery.createIn(context.getCurrentHqlPropertyPath() + ".oid", + return hibernateQuery.createIn(getBaseHqlPath() + ".oid", "select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1"); } @@ -74,6 +71,6 @@ public Condition interpret() throws QueryException { "ref.targetOid in (" + "select descendantOid from ROrgClosure where ancestorOid = :" + orgOidParamName + ")"; } - return hibernateQuery.createIn(context.getCurrentHqlPropertyPath() + ".oid", oidQueryText); + return hibernateQuery.createIn(getBaseHqlPath() + ".oid", oidQueryText); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index ae2fe5df831..2f513a4620d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -28,15 +29,16 @@ /** * @author lazyman */ -public class PropertyRestriction extends ItemRestriction { +public class PropertyRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(PropertyRestriction.class); PropertyDefinition propertyDefinition; - public PropertyRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition, PropertyDefinition propertyDefinition) { - super(rootEntityDefinition, startPropertyPath, startEntityDefinition); - Validate.notNull(propertyDefinition); + public PropertyRestriction(InterpretationContext context, ValueFilter filter, EntityDefinition baseEntityDefinition, + Restriction parent, PropertyDefinition propertyDefinition) { + super(context, filter, baseEntityDefinition, parent); + Validate.notNull(propertyDefinition, "propertyDefinition"); this.propertyDefinition = propertyDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index bb405108015..638872dd77b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -24,11 +24,10 @@ import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.ProperDefinitionSearchResult; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; @@ -37,6 +36,7 @@ import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; import java.util.List; @@ -44,15 +44,21 @@ /** * @author lazyman */ -public class ReferenceRestriction extends ItemRestriction { +public class ReferenceRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(ReferenceRestriction.class); - public ReferenceRestriction(EntityDefinition rootEntityDefinition, String startPropertyPath, EntityDefinition startEntityDefinition) { - super(rootEntityDefinition, startPropertyPath, startEntityDefinition); + // Definition of the item being queried. + // We cannot expect ReferenceDefinition here, because of multivalued references (e.g. linkRef) that have CollectionDefinition. + private final Definition itemDefinition; + + public ReferenceRestriction(InterpretationContext context, RefFilter filter, EntityDefinition baseEntityDefinition, + Restriction parent, Definition itemDefinition) { + super(context, filter, baseEntityDefinition, parent); + Validate.notNull(itemDefinition, "itemDefinition"); + this.itemDefinition = itemDefinition; } - // modelled after PropertyRestriction.interpretInternal, with some differences @Override public Condition interpretInternal(String hqlPath) throws QueryException { @@ -69,20 +75,14 @@ public Condition interpretInternal(String hqlPath) throws QueryException { InterpretationContext context = getContext(); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - ItemPath fullPath = getFullPath(filter.getPath()); - ProperDefinitionSearchResult defResult = context.findProperDefinition(fullPath, Definition.class); - if (defResult == null || defResult.getItemDefinition() == null) { - throw new QueryException("Definition for " + fullPath + " couldn't be found."); - } - Definition definition = defResult.getItemDefinition(); // actually, we cannot expect ReferenceDefinition here, because e.g. linkRef has a CollectionDefinition String propertyFullNamePrefix; - if (definition instanceof CollectionDefinition) { + if (itemDefinition instanceof CollectionDefinition) { propertyFullNamePrefix = hqlPath + "."; - } else if (definition instanceof ReferenceDefinition) { - propertyFullNamePrefix = hqlPath + "." + definition.getJpaName() + "."; + } else if (itemDefinition instanceof ReferenceDefinition) { + propertyFullNamePrefix = hqlPath + "." + itemDefinition.getJpaName() + "."; } else { - throw new IllegalStateException("Unexpected kind of Definition while processing ReferenceRestriction: " + definition); + throw new IllegalStateException("Unexpected kind of Definition while processing ReferenceRestriction: " + itemDefinition); } String refValueOid = null; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index 3a92703fd56..2af41a7a1eb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -17,24 +17,41 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.InterpreterHelper; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; +import org.apache.commons.lang.Validate; import org.hibernate.Session; -import java.util.List; - /** * An image of an ObjectFilter, forming a restriction tree. * Preserves some state related to the interpretation (translation). * Provides functionality related to the translation. * + * As for the state, we maintain (or, more precisely, we are able to determine) the following: + * - base ItemPath for the restriction + * - base HQL property path for the restriction + * - base EntityDefinition for the restriction + * (plus, as a convenience method, the same for children of this restriction) + * + * Most restrictions do not change the above properties when propagating them to their children. + * However, Type and Exists restrictions do. + * The former changes EntityDefinition, the latter all the three. + * + * Also, item-related restrictions may, at their own discretion, use an EntityDefinition that + * points to a subclass of the one provided by the parent restriction. They do that if the item + * referenced (e.g. location) is not available in the provided entity (e.g. RObject or RFocus or RAbstractRole), + * but has to be found deeper. + * + * There is one known problem in this respect, though: locality attribute. It is present in UserType as well as + * in OrgType. So, if having query like ObjectType: Equals(locality, 'abc') it might be narrowed + * as o.localityUser or o.locality. (Maybe there are other attributes like that, I don't know.) + * * @author lazyman * @author mederly */ @@ -44,6 +61,25 @@ public abstract class Restriction { protected Restriction parent; protected T filter; + /** + * Entity definition to be used as "root" by this restriction and its children. + * + * Looks a bit weird, but entity definition is provided to the restriction by the caller (query interpreter). + * Actually, the caller has to determine it, because it needs it to know what restriction to instantiate. + * (TODO reconsider this) + */ + protected EntityDefinition baseEntityDefinition; + + public Restriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + Validate.notNull(context, "context"); + Validate.notNull(filter, "filter"); + Validate.notNull(baseEntityDefinition, "baseEntityDefinition"); + this.context = context; + this.filter = filter; + this.parent = parent; + this.baseEntityDefinition = baseEntityDefinition; + } + public T getFilter() { return filter; } @@ -82,6 +118,44 @@ protected String nameOf(Enum e) { return e.getClass().getName() + "." + e.name(); } + /** + * HQL property path of the object to which this restriction is to be applied. + * + * Usually, e.g. for simple cases like UserType: name, UserType: activation/administrativeStatus etc. the root + * is the query primary entity alias (e.g. u in "RUser u"). + * + * For "Exists" filters children the base corresponds to the base item pointed to by the filter. + * E.g. + * - in "UserType: Exists (assignment)" it is "a" (provided that there is + * "RUser u left join u.assignments a with ..." already defined). + * - in "UserType: Exists (assignment/activation)" it is "a.activation" + * [although note that using single-valued properties as last path item + * in "Exists" filter is only a syntactic sugar] + */ + public String getBaseHqlPath() { + if (parent == null) { + return context.getHibernateQuery().getPrimaryEntityAlias(); + } else { + return parent.getBaseHqlPathForChildren(); + } + } + + /** + * HQL property path for children of this restriction. + * By default it is the same as base path for this one; however subclasses (namely Exists) may change that. + */ + public String getBaseHqlPathForChildren() { + return getBaseHqlPath(); + } + + public ItemPath getBaseItemPath() { + if (parent == null) { + return ItemPath.EMPTY_PATH; + } else { + return parent.getBaseItemPathForChildren(); + } + } + /** * Returns the item path that is the "base" path for any child restrictions. * Default is the empty path. @@ -89,12 +163,8 @@ protected String nameOf(Enum e) { * Currently, only the ForValue filter/restriction changes this path. E.g. for UserType: ForValue (assignment) * changes the base path for its children to "assignment". */ - public ItemPath getItemPathForChildren() { - if (parent != null) { - return parent.getItemPathForChildren(); // by default, restrictions don't change the reference path - } else { - return ItemPath.EMPTY_PATH; - } + public ItemPath getBaseItemPathForChildren() { + return getBaseItemPath(); } /** @@ -104,10 +174,35 @@ public ItemPath getItemPathForChildren() { * @return */ protected ItemPath getFullPath(ItemPath path) { - if (parent != null) { - return new ItemPath(parent.getItemPathForChildren(), path); - } else { - return path; - } - } + return new ItemPath(parent.getBaseItemPath(), path); + } + + public EntityDefinition getBaseEntityDefinition() { + return baseEntityDefinition; + } + + public EntityDefinition getBaseEntityDefinitionForChildren() { + return getBaseEntityDefinition(); + } + + protected InterpreterHelper getHelper() { + return getContext().getHelper(); + } + +// /** +// * Finds TypeFilter that is applicable in a current context. +// * Simple algorithm is to check all the parents. +// * More complex one (not yet implemented) would be to check also sibling restrictions in an AndRestriction, if +// * there's any. +// * +// * @return +// */ +// public TypeFilter findApplicableTypeFilter() { +// if (parent != null) { +// return parent.findApplicableTypeFilter(); +// } else { +// return null; +// } +// } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java index 70f46eb5183..58ae82e5dd8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; @@ -36,12 +37,16 @@ */ public class TypeRestriction extends Restriction { + public TypeRestriction(InterpretationContext context, TypeFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + @Override public Condition interpret() throws QueryException { InterpretationContext context = getContext(); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - String property = context.getCurrentHqlPropertyPath() + "." + RObject.F_OBJECT_TYPE_CLASS; + String property = getBaseHqlPath() + "." + RObject.F_OBJECT_TYPE_CLASS; Set values = getValues(filter.getType()); @@ -57,7 +62,7 @@ public Condition interpret() throws QueryException { } QueryInterpreter2 interpreter = context.getInterpreter(); - Condition basedOnFilter = interpreter.interpretFilter(filter.getFilter(), context, this); + Condition basedOnFilter = interpreter.interpretFilter(context, filter.getFilter(), this); return hibernateQuery.createAnd(basedOnType, basedOnFilter); } @@ -83,5 +88,4 @@ private Set getValues(QName typeQName) { return set; } - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java index c9204703543..eaaddffbec7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; +import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -31,10 +32,14 @@ public abstract class UnaryLogicalRestriction exte private static final Trace LOGGER = TraceManager.getTrace(UnaryLogicalRestriction.class); + public UnaryLogicalRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + super(context, filter, baseEntityDefinition, parent); + } + protected Condition interpretChildFilter() throws QueryException { InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); - return interpreter.interpretFilter(filter.getFilter(), context, this); + return interpreter.interpretFilter(context, filter.getFilter(), this); } protected void validateFilter() throws QueryException { From 587daf739ffc12d721d7fa61ff2e800a236ed791 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 25 Nov 2015 13:16:58 +0100 Subject: [PATCH 014/116] Tests for "Exists" filter. Replaced CollectionDefinition by CollectionSpecification attribute. Got rid of (almost all) non-prism items in entity definition registry. --- .../midpoint/prism/query/ExistsFilter.java | 11 +- .../midpoint/prism/query/GreaterFilter.java | 6 +- .../midpoint/prism/query/LessFilter.java | 10 +- .../repo/sql/QueryInterpreter2Test.java | 282 +++++++++++++----- .../midpoint/repo/sql/data/common/RFocus.java | 2 + .../repo/sql/data/common/RFocusPhoto.java | 3 + .../repo/sql/data/common/RObject.java | 19 ++ .../sql/data/common/RObjectReference.java | 4 +- .../repo/sql/data/common/ROrgClosure.java | 6 + .../sql/data/common/any/RAExtBoolean.java | 4 + .../repo/sql/data/common/any/RAExtDate.java | 4 + .../repo/sql/data/common/any/RAExtLong.java | 4 + .../sql/data/common/any/RAExtPolyString.java | 4 + .../sql/data/common/any/RAExtReference.java | 4 + .../repo/sql/data/common/any/RAExtString.java | 4 + .../data/common/any/RAssignmentExtension.java | 3 +- .../sql/data/common/any/ROExtBoolean.java | 2 + .../repo/sql/data/common/any/ROExtDate.java | 2 + .../repo/sql/data/common/any/ROExtLong.java | 3 +- .../sql/data/common/any/ROExtPolyString.java | 2 + .../sql/data/common/any/ROExtReference.java | 2 + .../repo/sql/data/common/any/ROExtString.java | 2 + .../container/RAccessCertificationCase.java | 4 + .../data/common/container/RAssignment.java | 4 + .../container/RAssignmentReference.java | 4 + .../common/container/RCertCaseReference.java | 5 +- .../common/container/RContainerReference.java | 4 + .../sql/data/common/container/RExclusion.java | 2 + .../sql/data/common/container/RTrigger.java | 4 + .../data/common/other/RLookupTableRow.java | 2 + .../sql/query2/DefinitionSearchResult.java | 4 +- .../repo/sql/query2/InterpreterHelper.java | 31 +- .../query2/ProperDefinitionSearchResult.java | 6 +- .../sql/query2/QueryDefinitionRegistry2.java | 3 + .../repo/sql/query2/QueryInterpreter2.java | 17 +- .../sql/query2/definition/AnyDefinition.java | 2 +- .../definition/ClassDefinitionParser.java | 117 ++++---- .../definition/CollectionDefinition.java | 82 ----- .../definition/CollectionSpecification.java | 31 ++ .../sql/query2/definition/Definition.java | 51 ++-- .../definition/DefinitionComparator.java | 2 - .../query2/definition/EntityDefinition.java | 36 +-- .../sql/query2/definition/NotQueryable.java | 31 ++ .../query2/definition/PropertyDefinition.java | 6 +- .../definition/ReferenceDefinition.java | 6 +- ...va => VirtualCollectionSpecification.java} | 16 +- .../definition/VirtualEntityDefinition.java | 8 +- .../definition/VirtualPropertyDefinition.java | 8 +- .../repo/sql/query2/hqm/HibernateQuery.java | 8 +- .../restriction/CollectionRestriction.java | 52 ---- .../query2/restriction/ExistsRestriction.java | 2 +- .../restriction/PropertyRestriction.java | 7 +- .../restriction/ReferenceRestriction.java | 10 +- 53 files changed, 535 insertions(+), 413 deletions(-) delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{VirtualCollectionDefinition.java => VirtualCollectionSpecification.java} (66%) delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java index 705c42ed95a..fed5b14496c 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.path.ItemPath; @@ -60,12 +61,18 @@ public ObjectFilter getFilter() { return filter; } - public static ExistsFilter createEqual(ItemPath itemPath, PrismContainerDefinition containerDef, - ObjectFilter filter) throws SchemaException { + public static ExistsFilter createEquals(ItemPath itemPath, PrismContainerDefinition containerDef, + ObjectFilter filter) throws SchemaException { ItemDefinition itemDefinition = FilterUtils.findItemDefinition(itemPath, containerDef); return new ExistsFilter(itemPath, itemDefinition, filter); } + public static ExistsFilter createEquals(ItemPath itemPath, Class clazz, PrismContext prismContext, + ObjectFilter filter) throws SchemaException { + ItemDefinition itemDefinition = FilterUtils.findItemDefinition(itemPath, clazz, prismContext); + return new ExistsFilter(itemPath, itemDefinition, filter); + } + @Override public ObjectFilter clone() { ObjectFilter f = filter != null ? filter.clone() : null; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java index 7d4b0bcf9b1..76171b423eb 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java @@ -18,6 +18,8 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.Objectable; @@ -44,7 +46,7 @@ public static GreaterFilter createGreater(ItemPath par return new GreaterFilter(parentPath, definition, value, equals); } - public static GreaterFilter createGreater(ItemPath parentPath, PrismObjectDefinition containerDef, + public static GreaterFilter createGreater(ItemPath parentPath, PrismContainerDefinition containerDef, PrismPropertyValue value, boolean equals) throws SchemaException { PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createGreater(parentPath, def, value, equals); @@ -60,7 +62,7 @@ public static GreaterFilter createGreater(ItemPath parentPath, PrismProperty return createGreater(parentPath, itemDefinition, value, equals); } - public static GreaterFilter createGreater(ItemPath parentPath, PrismObjectDefinition containerDef, + public static GreaterFilter createGreater(ItemPath parentPath, PrismContainerDefinition containerDef, T realValue, boolean equals) throws SchemaException { PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createGreater(parentPath, def, realValue, equals); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java index 31be0f48915..67d57e5e228 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java @@ -18,7 +18,9 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObjectDefinition; @@ -38,16 +40,16 @@ public class LessFilter extends ComparativeFilter { public LessFilter() { } - public static LessFilter createLess(QName parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ + public static LessFilter createLess(QName parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ return new LessFilter(new ItemPath(parentPath), definition, value, equals); } - public static LessFilter createLess(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ + public static LessFilter createLess(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ return new LessFilter(parentPath, definition, value, equals); } - public static LessFilter createLess(ItemPath parentPath, PrismObjectDefinition containerDef, + public static LessFilter createLess(ItemPath parentPath, PrismContainerDefinition containerDef, PrismPropertyValue value, boolean equals) throws SchemaException { PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createLess(parentPath, def, value, equals); @@ -67,7 +69,7 @@ public static LessFilter createLess(ItemPath parentPath, PrismPropertyDefini return createLess(parentPath, itemDefinition, value, equals); } - public static LessFilter createLess(ItemPath parentPath, PrismObjectDefinition containerDef, + public static LessFilter createLess(ItemPath parentPath, PrismContainerDefinition containerDef, T realValue, boolean equals) throws SchemaException { PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); return createLess(parentPath, def, realValue, equals); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index ed942b4afce..529f3173125 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.AndFilter; import com.evolveum.midpoint.prism.query.EqualFilter; +import com.evolveum.midpoint.prism.query.ExistsFilter; import com.evolveum.midpoint.prism.query.GreaterFilter; import com.evolveum.midpoint.prism.query.InOidFilter; import com.evolveum.midpoint.prism.query.LessFilter; @@ -42,35 +43,16 @@ import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.repo.sql.data.common.RConnector; -import com.evolveum.midpoint.repo.sql.data.common.RGenericObject; -import com.evolveum.midpoint.repo.sql.data.common.RObject; -import com.evolveum.midpoint.repo.sql.data.common.RObjectReference; -import com.evolveum.midpoint.repo.sql.data.common.ROrg; -import com.evolveum.midpoint.repo.sql.data.common.ROrgClosure; -import com.evolveum.midpoint.repo.sql.data.common.RReportOutput; -import com.evolveum.midpoint.repo.sql.data.common.RRole; -import com.evolveum.midpoint.repo.sql.data.common.RShadow; -import com.evolveum.midpoint.repo.sql.data.common.RTask; -import com.evolveum.midpoint.repo.sql.data.common.RUser; -import com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus; -import com.evolveum.midpoint.repo.sql.data.common.enums.RTaskExecutionStatus; -import com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner; -import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; -import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; -import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.RQuery; import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; import com.evolveum.midpoint.repo.sql.query2.RQueryImpl; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; -import com.evolveum.midpoint.repo.sql.util.HibernateToSqlTranslator; import com.evolveum.midpoint.schema.MidPointPrismContextFactory; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.PrettyPrinter; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -87,7 +69,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportOutputType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStatusType; @@ -95,19 +76,9 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.apache.commons.lang.StringUtils; -import org.hibernate.Criteria; import org.hibernate.Session; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.DetachedCriteria; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Order; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Property; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.Subqueries; -import org.hibernate.sql.JoinType; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; @@ -120,14 +91,13 @@ import javax.xml.namespace.QName; import java.io.File; import java.io.IOException; -import java.sql.Timestamp; -import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; /** * @author lazyman + * @author mederly */ @ContextConfiguration(locations = {"../../../../../ctx-test.xml"}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @@ -161,7 +131,7 @@ public void beforeClass() throws Exception { AssertJUnit.assertTrue(result.isSuccess()); } - @Test(enabled = false) + @Test public void test001QueryNameNorm() throws Exception { Session session = open(); @@ -187,7 +157,7 @@ public void test001QueryNameNorm() throws Exception { } } - @Test(enabled = false) + @Test public void test002QueryNameOrig() throws Exception { Session session = open(); @@ -213,7 +183,7 @@ public void test002QueryNameOrig() throws Exception { } } - @Test(enabled = false) + @Test public void test003QueryNameStrict() throws Exception { Session session = open(); @@ -239,7 +209,7 @@ public void test003QueryNameStrict() throws Exception { } } - @Test(enabled = false) + @Test public void test010QueryOrganizationNorm() throws Exception { Session session = open(); @@ -278,7 +248,7 @@ private void assertEqualsIgnoreWhitespace(String expected, String real) { } } - @Test(enabled = false) + @Test public void test011QueryOrganizationOrig() throws Exception { Session session = open(); try { @@ -304,7 +274,7 @@ public void test011QueryOrganizationOrig() throws Exception { } } - @Test(enabled = false) + @Test public void test012QueryOrganizationStrict() throws Exception { Session session = open(); try { @@ -331,7 +301,7 @@ public void test012QueryOrganizationStrict() throws Exception { } } - @Test(enabled = false) + @Test public void test020QueryTwoOrganizationsNormAnd() throws Exception { Session session = open(); try { @@ -361,7 +331,7 @@ public void test020QueryTwoOrganizationsNormAnd() throws Exception { } } - @Test(enabled = false) + @Test public void test021QueryTwoOrganizationsStrictOr() throws Exception { Session session = open(); try { @@ -395,7 +365,7 @@ public void test021QueryTwoOrganizationsStrictOr() throws Exception { } } - @Test(enabled = false) + @Test public void test025QueryOrganizationOrigPolymorphic() throws Exception { Session session = open(); try { @@ -421,7 +391,7 @@ public void test025QueryOrganizationOrigPolymorphic() throws Exception { } } - @Test(enabled = false) + @Test public void test030QueryTaskDependent() throws Exception { Session session = open(); @@ -462,7 +432,7 @@ public void test040QueryClob() throws Exception { } } - @Test(enabled = false) + @Test public void test050QueryEnum() throws Exception { Session session = open(); try { @@ -493,7 +463,7 @@ public void test050QueryEnum() throws Exception { } } - @Test(enabled = false) + @Test public void test060QueryEnabled() throws Exception { Session session = open(); try { @@ -524,7 +494,7 @@ public void test060QueryEnabled() throws Exception { } } - @Test(enabled = false) + @Test public void test070QueryGenericLong() throws Exception { Session session = open(); try { @@ -545,7 +515,7 @@ public void test070QueryGenericLong() throws Exception { " g.fullObject, g.stringsCount, g.longsCount, g.datesCount, g.referencesCount, g.polysCount, g.booleansCount\n" + "from\n" + " RGenericObject g\n" + - " left join g.longs l with (l.ownerType = :ownerType and l.name = :name)\n" + + " left join g.longs l with ( l.ownerType = :ownerType and l.name = :name )\n" + "where\n" + " ( g.name.norm = :norm and l.value = :value )\n"; @@ -555,7 +525,7 @@ public void test070QueryGenericLong() throws Exception { } } - @Test(enabled = false) + @Test public void test072QueryAccountByAttribute() throws Exception { Session session = open(); try { @@ -656,6 +626,27 @@ public void test076QueryOrComposite() throws Exception { } } + @Test + public void test080QueryExistsAssignment() throws Exception { + Session session = open(); + + try { + /* + * ### UserType: Exists (assignment, Equal (activation/administrativeStatus = Enabled)) + */ + ExistsFilter filter = ExistsFilter.createEquals(new ItemPath(UserType.F_ASSIGNMENT), UserType.class, prismContext, + EqualFilter.createEqual(new ItemPath(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), + AssignmentType.class, prismContext, null, ActivationStatusType.ENABLED)); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); + + String real = getInterpretedQuery(session, UserType.class, query); + //assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test100QueryObjectByName() throws Exception { Session session = open(); @@ -1297,41 +1288,95 @@ public void test340QueryOrgTreeFindOrgs() throws Exception { } } - @Test(enabled = false) - public void asdf() throws Exception { - Session session = open(); - try { - Criteria main = session.createCriteria(RUser.class, "u"); - Criteria a = main.createCriteria("assignments", "a"); - a.add(Restrictions.eq("a.assignmentOwner", RAssignmentOwner.FOCUS)); - Criteria e = a.createCriteria("a.extension"); +// @Test +// public void asdf() throws Exception { +// Session session = open(); +// try { +// Criteria main = session.createCriteria(RUser.class, "u"); +// Criteria a = main.createCriteria("assignments", "a"); +// a.add(Restrictions.eq("a.assignmentOwner", RAssignmentOwner.FOCUS)); +// Criteria e = a.createCriteria("a.extension"); +// +// Criteria s = e.createCriteria("strings", "s"); +// +// Conjunction c2 = Restrictions.conjunction(); +// c2.add(Restrictions.eq("s.extensionType", RAssignmentExtensionType.EXTENSION)); +// c2.add(Restrictions.eq("s.name", new QName("http://midpoint.evolveum.com/blabla", "foo"))); +// c2.add(Restrictions.eq("s.value", "uid=jbond,ou=People,dc=example,dc=com")); +// +// Conjunction c1 = Restrictions.conjunction(); +// c1.add(Restrictions.eq("a.targetRef.targetOid", "1234")); +// c1.add(Restrictions.eq("a.targetRef.type", RObjectType.ORG)); +// +// main.add(Restrictions.and(c1, c2)); +// +// main.setProjection(Projections.property("u.fullObject")); +// +// String expected = HibernateToSqlTranslator.toSql(main); +// LOGGER.info(">>> >>> {}", expected); +// } finally { +// close(session); +// } +// } - Criteria s = e.createCriteria("strings", "s"); + @Test + public void test400ActivationQueryWrong() throws Exception { + PrismObjectDefinition focusObjectDef = prismContext.getSchemaRegistry() + .findObjectDefinitionByCompileTimeClass(UserType.class); - Conjunction c2 = Restrictions.conjunction(); - c2.add(Restrictions.eq("s.extensionType", RAssignmentExtensionType.EXTENSION)); - c2.add(Restrictions.eq("s.name", new QName("http://midpoint.evolveum.com/blabla", "foo"))); - c2.add(Restrictions.eq("s.value", "uid=jbond,ou=People,dc=example,dc=com")); + XMLGregorianCalendar thisScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); - Conjunction c1 = Restrictions.conjunction(); - c1.add(Restrictions.eq("a.targetRef.targetOid", "1234")); - c1.add(Restrictions.eq("a.targetRef.type", RObjectType.ORG)); + OrFilter filter = OrFilter.createOr( + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, + thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, + thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + focusObjectDef, thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + focusObjectDef, thisScanTimestamp, true) + ); + + Session session = open(); + try { + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, UserType.class, query, false); - main.add(Restrictions.and(c1, c2)); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + " left join u.assignments a2 with a2.assignmentOwner = :assignmentOwner2\n" + + "where\n" + + " (\n" + + " u.activation.validFrom <= :validFrom or\n" + + " u.activation.validTo <= :validTo or\n" + + " a.activation.validFrom <= :validFrom2 or\n" + + " a2.activation.validTo <= :validTo2\n" + + " )\n"; - main.setProjection(Projections.property("u.fullObject")); + // correct translation but probably not what the requester wants (use Exists instead) - String expected = HibernateToSqlTranslator.toSql(main); - LOGGER.info(">>> >>> {}", expected); + assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); } } + // this one uses Exists to refer to the same value of assignment @Test - public void test400ActivationQueryWrong() throws Exception { + public void test405ActivationQueryCorrect() throws Exception { PrismObjectDefinition focusObjectDef = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(UserType.class); + PrismContainerDefinition assignmentDef = prismContext.getSchemaRegistry() + .findContainerDefinitionByCompileTimeClass(AssignmentType.class); XMLGregorianCalendar thisScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); @@ -1340,11 +1385,12 @@ public void test400ActivationQueryWrong() throws Exception { thisScanTimestamp, true), LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), - focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), - focusObjectDef, thisScanTimestamp, true) - ); + ExistsFilter.createEquals(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, + OrFilter.createOr( + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + assignmentDef, thisScanTimestamp, true), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + assignmentDef, thisScanTimestamp, true)))); Session session = open(); try { @@ -1362,13 +1408,12 @@ public void test400ActivationQueryWrong() throws Exception { "from\n" + " RUser u\n" + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + - " left join u.assignments a2 with a2.assignmentOwner = :assignmentOwner2\n" + "where\n" + " (\n" + " u.activation.validFrom <= :validFrom or\n" + " u.activation.validTo <= :validTo or\n" + - " a.activation.validFrom <= :validFrom2 or\n" + - " a2.activation.validTo <= :validTo2\n" + + " ( a.activation.validFrom <= :validFrom2 or\n" + + " a.activation.validTo <= :validTo2 )\n" + " )\n"; // correct translation but probably not what the requester wants (use ForValue instead) @@ -1460,6 +1505,91 @@ public void test410ActivationQueryWrong() throws Exception { } } + // this one uses Exists to refer to the same value of assignment + @Test + public void test415ActivationQueryCorrect() throws Exception { + PrismObjectDefinition focusObjectDef = prismContext.getSchemaRegistry() + .findObjectDefinitionByCompileTimeClass(UserType.class); + PrismContainerDefinition assignmentDef = prismContext.getSchemaRegistry() + .findContainerDefinitionByCompileTimeClass(AssignmentType.class); + + XMLGregorianCalendar lastScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); + XMLGregorianCalendar thisScanTimestamp = XMLGregorianCalendarType.asXMLGregorianCalendar(new Date()); + + OrFilter filter = OrFilter.createOr( + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, + lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, + thisScanTimestamp, true) + ), + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, + lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, + thisScanTimestamp, true) + ), + AndFilter.createAnd( + ExistsFilter.createEquals(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, + OrFilter.createOr( + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + assignmentDef, lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + assignmentDef, thisScanTimestamp, true) + ), + AndFilter.createAnd( + GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + assignmentDef, lastScanTimestamp, false), + LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + assignmentDef, thisScanTimestamp, true)))) + ) + ); + + Session session = open(); + try { + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery(session, UserType.class, query, false); + + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "where\n" + + " (\n" + + " (\n" + + " u.activation.validFrom > :validFrom and\n" + + " u.activation.validFrom <= :validFrom2\n" + + " ) or\n" + + " (\n" + + " u.activation.validTo > :validTo and\n" + + " u.activation.validTo <= :validTo2\n" + + " ) or\n" + + " ( (\n" + + " a.activation.validFrom > :validFrom3 and\n" + + " a.activation.validFrom <= :validFrom4\n" + + " ) or\n" + + " (\n" + + " a.activation.validTo > :validTo3 and\n" + + " a.activation.validTo <= :validTo4\n" + + " )\n" + + " )\n" + + " )\n"; + + // TODO rewrite with ForValue + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test500OrgQuery() throws Exception { File objects = new File("src/test/resources/orgstruct/org-monkey-island.xml"); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java index 6db5426f4f3..fec48cbf379 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java @@ -25,6 +25,7 @@ import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -112,6 +113,7 @@ public Set getAssignment() { @OneToMany(mappedBy = RAssignment.F_OWNER, orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) + @NotQueryable // virtual definition is used instead public Set getAssignments() { if (assignments == null) { assignments = new HashSet<>(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocusPhoto.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocusPhoto.java index 56b359e5eb9..623d5dfc004 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocusPhoto.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocusPhoto.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.data.common; import com.evolveum.midpoint.repo.sql.data.common.id.RFocusPhotoId; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; @@ -41,12 +42,14 @@ public class RFocusPhoto implements Serializable { @ForeignKey(name = "fk_focus_photo") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RFocus getOwner() { return owner; } @Id @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && owner != null) { ownerOid = owner.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 8a20f5bf462..92a8b8f2081 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -35,6 +35,7 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.util.ClassMapper; @@ -161,6 +162,7 @@ public abstract class RObject implements Metadata getParentOrgRef() { return parentOrgRef; } + @NotQueryable @OneToMany(fetch = FetchType.LAZY, targetEntity = ROrgClosure.class, mappedBy = "descendant") @Cascade({org.hibernate.annotations.CascadeType.DELETE}) public Set getDescendants() { return descendants; } + @NotQueryable @OneToMany(fetch = FetchType.LAZY, targetEntity = ROrgClosure.class, mappedBy = "ancestor")//, orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.DELETE}) public Set getAncestors() { return ancestors; } + @NotQueryable public int getVersion() { return version; } @@ -212,6 +217,7 @@ public REmbeddedReference getTenantRef() { } @Lob + @NotQueryable public byte[] getFullObject() { return fullObject; } @@ -264,6 +270,7 @@ public XMLGregorianCalendar getModifyTimestamp() { return modifyTimestamp; } + @NotQueryable @OneToMany(mappedBy = "owner", orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getLongs() { @@ -273,6 +280,7 @@ public Set getLongs() { return longs; } + @NotQueryable @OneToMany(mappedBy = "owner", orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getBooleans() { @@ -282,6 +290,7 @@ public Set getBooleans() { return booleans; } + @NotQueryable @OneToMany(mappedBy = "owner", orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getStrings() { @@ -291,6 +300,7 @@ public Set getStrings() { return strings; } + @NotQueryable @OneToMany(mappedBy = "owner", orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getDates() { @@ -300,6 +310,7 @@ public Set getDates() { return dates; } + @NotQueryable @OneToMany(mappedBy = "owner", orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getReferences() { @@ -309,6 +320,7 @@ public Set getReferences() { return references; } + @NotQueryable @OneToMany(mappedBy = "owner", orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getPolys() { @@ -318,6 +330,7 @@ public Set getPolys() { return polys; } + @NotQueryable public Short getStringsCount() { if (stringsCount == null) { stringsCount = 0; @@ -325,6 +338,7 @@ public Short getStringsCount() { return stringsCount; } + @NotQueryable public Short getBooleansCount() { if (booleansCount == null) { booleansCount = 0; @@ -332,6 +346,7 @@ public Short getBooleansCount() { return booleansCount; } + @NotQueryable public Short getLongsCount() { if (longsCount == null) { longsCount = 0; @@ -339,6 +354,7 @@ public Short getLongsCount() { return longsCount; } + @NotQueryable public Short getDatesCount() { if (datesCount == null) { datesCount = 0; @@ -346,6 +362,7 @@ public Short getDatesCount() { return datesCount; } + @NotQueryable public Short getReferencesCount() { if (referencesCount == null) { referencesCount = 0; @@ -353,6 +370,7 @@ public Short getReferencesCount() { return referencesCount; } + @NotQueryable public Short getPolysCount() { if (polysCount == null) { polysCount = 0; @@ -361,6 +379,7 @@ public Short getPolysCount() { } @Enumerated + @NotQueryable public RObjectType getObjectTypeClass() { return objectTypeClass; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java index c35a2753bb8..afc50f27c79 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java @@ -21,13 +21,13 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import org.apache.commons.lang.Validate; import org.hibernate.annotations.ForeignKey; -import org.hibernate.annotations.Index; import javax.persistence.*; @@ -62,12 +62,14 @@ public RObjectReference() { @ForeignKey(name = "fk_reference_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } @Id @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && owner != null) { ownerOid = owner.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/ROrgClosure.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/ROrgClosure.java index ba64a0f7570..5a320270ba3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/ROrgClosure.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/ROrgClosure.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.data.common; import com.evolveum.midpoint.repo.sql.data.common.id.ROrgClosureId; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -33,6 +34,7 @@ @org.hibernate.annotations.Table(appliesTo = "m_org_closure", indexes = {@Index(name = "iDescendant", columnNames = {"descendant_oid"}), @Index(name = "iDescendantAncestor", columnNames = {"descendant_oid", "ancestor_oid"})}) +@NotQueryable public class ROrgClosure implements Serializable { private RObject ancestor; @@ -66,6 +68,7 @@ public ROrgClosure(RObject ancestor, RObject descendant, int val) { @ManyToOne(fetch = FetchType.LAZY, optional = true) @JoinColumns({@JoinColumn(name = "ancestor_oid", referencedColumnName = "oid")}) @ForeignKey(name = "fk_ancestor") + @NotQueryable public RObject getAncestor() { return ancestor; } @@ -73,6 +76,7 @@ public RObject getAncestor() { @Id @Index(name = "iAncestor") @Column(name = "ancestor_oid", length = RUtil.COLUMN_LENGTH_OID, insertable = false, updatable = false) + @NotQueryable public String getAncestorOid() { if (ancestorOid == null && ancestor.getOid() != null) { ancestorOid = ancestor.getOid(); @@ -88,6 +92,7 @@ public void setAncestor(RObject ancestor) { @ManyToOne(fetch = FetchType.LAZY, optional = true) @JoinColumns({@JoinColumn(name = "descendant_oid", referencedColumnName = "oid")}) @ForeignKey(name = "fk_descendant") + @NotQueryable public RObject getDescendant() { return descendant; } @@ -95,6 +100,7 @@ public RObject getDescendant() { @Id @Index(name = "iDescendant") @Column(name = "descendant_oid", length = RUtil.COLUMN_LENGTH_OID, insertable = false, updatable = false) + @NotQueryable public String getDescendantOid() { if (descendantOid == null && descendant.getOid() != null) { descendantOid = descendant.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtBoolean.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtBoolean.java index fac8a6972ad..c5375ebfe61 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtBoolean.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtBoolean.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RAExtBooleanId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -62,12 +63,14 @@ public RAExtBoolean(Boolean value) { @PrimaryKeyJoinColumn(name = "anyContainer_owner_owner_oid", referencedColumnName = "ownerOid"), @PrimaryKeyJoinColumn(name = "anyContainer_owner_id", referencedColumnName = "owner_type") }) + @NotQueryable public RAssignmentExtension getAnyContainer() { return anyContainer; } @Id @Column(name = "anyContainer_owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && anyContainer != null) { ownerOid = anyContainer.getOwnerOid(); @@ -77,6 +80,7 @@ public String getOwnerOid() { @Id @Column(name = "anyContainer_owner_id") + @NotQueryable public Integer getOwnerId() { if (ownerId == null && anyContainer != null) { ownerId = anyContainer.getOwnerId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtDate.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtDate.java index 4d7e816442a..7624a803022 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtDate.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtDate.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RAExtDateId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -63,12 +64,14 @@ public RAExtDate(Timestamp value) { @PrimaryKeyJoinColumn(name = "anyContainer_owner_owner_oid", referencedColumnName = "ownerOid"), @PrimaryKeyJoinColumn(name = "anyContainer_owner_id", referencedColumnName = "owner_type") }) + @NotQueryable public RAssignmentExtension getAnyContainer() { return anyContainer; } @Id @Column(name = "anyContainer_owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && anyContainer != null) { ownerOid = anyContainer.getOwnerOid(); @@ -78,6 +81,7 @@ public String getOwnerOid() { @Id @Column(name = "anyContainer_owner_id") + @NotQueryable public Integer getOwnerId() { if (ownerId == null && anyContainer != null) { ownerId = anyContainer.getOwnerId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtLong.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtLong.java index 6a84f1b8630..162c89ebae5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtLong.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtLong.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RAExtLongId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -62,12 +63,14 @@ public RAExtLong(Long value) { @PrimaryKeyJoinColumn(name = "anyContainer_owner_owner_oid", referencedColumnName = "ownerOid"), @PrimaryKeyJoinColumn(name = "anyContainer_owner_id", referencedColumnName = "owner_type") }) + @NotQueryable public RAssignmentExtension getAnyContainer() { return anyContainer; } @Id @Column(name = "anyContainer_owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && anyContainer != null) { ownerOid = anyContainer.getOwnerOid(); @@ -77,6 +80,7 @@ public String getOwnerOid() { @Id @Column(name = "anyContainer_owner_id") + @NotQueryable public Integer getOwnerId() { if (ownerId == null && anyContainer != null) { ownerId = anyContainer.getOwnerId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtPolyString.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtPolyString.java index 472edc76439..98588b0a53e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtPolyString.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtPolyString.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.repo.sql.data.common.id.RAExtPolyStringId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -69,12 +70,14 @@ public RAExtPolyString(PolyString polyString) { @PrimaryKeyJoinColumn(name = "anyContainer_owner_owner_oid", referencedColumnName = "ownerOid"), @PrimaryKeyJoinColumn(name = "anyContainer_owner_id", referencedColumnName = "owner_type") }) + @NotQueryable public RAssignmentExtension getAnyContainer() { return anyContainer; } @Id @Column(name = "anyContainer_owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && anyContainer != null) { ownerOid = anyContainer.getOwnerOid(); @@ -84,6 +87,7 @@ public String getOwnerOid() { @Id @Column(name = "anyContainer_owner_id") + @NotQueryable public Integer getOwnerId() { if (ownerId == null && anyContainer != null) { ownerId = anyContainer.getOwnerId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtReference.java index 250eb0465b7..1b113a7f1f1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtReference.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RAExtReferenceId; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; @@ -65,12 +66,14 @@ public RAExtReference() { @PrimaryKeyJoinColumn(name = "anyContainer_owner_owner_oid", referencedColumnName = "ownerOid"), @PrimaryKeyJoinColumn(name = "anyContainer_owner_id", referencedColumnName = "owner_type") }) + @NotQueryable public RAssignmentExtension getAnyContainer() { return anyContainer; } @Id @Column(name = "anyContainer_owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && anyContainer != null) { ownerOid = anyContainer.getOwnerOid(); @@ -80,6 +83,7 @@ public String getOwnerOid() { @Id @Column(name = "anyContainer_owner_id") + @NotQueryable public Integer getOwnerId() { if (ownerId == null && anyContainer != null) { ownerId = anyContainer.getOwnerId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtString.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtString.java index 620c6f31e9d..36af1a69185 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtString.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAExtString.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RAExtStringId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -62,12 +63,14 @@ public RAExtString(String value) { @PrimaryKeyJoinColumn(name = "anyContainer_owner_owner_oid", referencedColumnName = "ownerOid"), @PrimaryKeyJoinColumn(name = "anyContainer_owner_id", referencedColumnName = "ownerId") }) + @NotQueryable public RAssignmentExtension getAnyContainer() { return anyContainer; } @Id @Column(name = "anyContainer_owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { if (ownerOid == null && anyContainer != null) { ownerOid = anyContainer.getOwnerOid(); @@ -77,6 +80,7 @@ public String getOwnerOid() { @Id @Column(name = "anyContainer_owner_id") + @NotQueryable public Integer getOwnerId() { if (ownerId == null && anyContainer != null) { ownerId = anyContainer.getOwnerId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java index b3b10c23458..44d5a9ec417 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java @@ -22,10 +22,10 @@ import com.evolveum.midpoint.repo.sql.data.common.container.RAssignment; import com.evolveum.midpoint.repo.sql.data.common.id.RAssignmentExtensionId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExtensionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAttributesType; import org.apache.commons.lang.Validate; import org.hibernate.annotations.Cascade; @@ -67,6 +67,7 @@ public class RAssignmentExtension implements Serializable { @ForeignKey(name = "none") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RAssignment getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtBoolean.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtBoolean.java index 1cf84a7c6b5..2b1c5dad527 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtBoolean.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtBoolean.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.ROExtBooleanId; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -59,6 +60,7 @@ public ROExtBoolean(Boolean value) { @ForeignKey(name = "fk_object_ext_boolean") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtDate.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtDate.java index b928a7dbc85..efd78ad975f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtDate.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtDate.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.ROExtDateId; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -60,6 +61,7 @@ public ROExtDate(Timestamp value) { @ForeignKey(name = "fk_object_ext_date") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtLong.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtLong.java index 846eb1a9ae3..8a3678b9e76 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtLong.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtLong.java @@ -18,8 +18,8 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.ROExtLongId; -import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -60,6 +60,7 @@ public ROExtLong(Long value) { @ForeignKey(name = "fk_object_ext_long") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtPolyString.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtPolyString.java index 32b802e679f..d1c33232691 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtPolyString.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtPolyString.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.ROExtPolyStringId; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -66,6 +67,7 @@ public ROExtPolyString(PolyString polyString) { @ForeignKey(name = "fk_object_ext_poly") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtReference.java index a9cadac8fd2..c5079c9568c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtReference.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.ROExtReferenceId; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; @@ -62,6 +63,7 @@ public ROExtReference() { @ForeignKey(name = "fk_object_ext_reference") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtString.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtString.java index 5244dc9c52a..775456d4190 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtString.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/ROExtString.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.ROExtStringId; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; @@ -59,6 +60,7 @@ public ROExtString(String value) { @ForeignKey(name = "fk_object_ext_string") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index e17f4d1abf8..e8929598297 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -97,11 +98,13 @@ public RAccessCertificationCase(RObject owner) { @org.hibernate.annotations.ForeignKey(name = "fk_ac_case_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + @NotQueryable public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); @@ -113,6 +116,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") + @NotQueryable public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java index bcc0b72a127..580c79f847c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -108,11 +109,13 @@ public RAssignment(RObject owner, RAssignmentOwner assignmentOwner) { @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) // @JoinTable(foreignKey = @ForeignKey(name = "fk_assignment_owner")) + @NotQueryable public RObject getOwner() { return owner; } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + @NotQueryable public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); @@ -124,6 +127,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") + @NotQueryable public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java index f99728fc316..ff2a0b9e480 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; @@ -43,12 +44,14 @@ public class RAssignmentReference extends RContainerReference { @ForeignKey(name = "fk_assignment_reference") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RAssignment getOwner() { return owner; } @Id @Column(name = "owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { return super.getOwnerOid(); } @@ -56,6 +59,7 @@ public String getOwnerOid() { @Id @Column(name = "owner_id") + @NotQueryable public Integer getOwnerId() { return super.getOwnerId(); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java index 27508e8a6d9..d1b6ea00117 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java @@ -17,11 +17,11 @@ package com.evolveum.midpoint.repo.sql.data.common.container; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.id.RCObjectReferenceId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import org.apache.commons.lang.Validate; @@ -67,12 +67,14 @@ public class RCertCaseReference extends RContainerReference { @ForeignKey(name = "fk_acc_cert_case_reference") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RAccessCertificationCase getOwner() { return owner; } @Id @Column(name = "owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID) + @NotQueryable public String getOwnerOid() { return super.getOwnerOid(); } @@ -80,6 +82,7 @@ public String getOwnerOid() { @Id @Column(name = "owner_id") + @NotQueryable public Integer getOwnerId() { return super.getOwnerId(); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java index 1e474fa4e71..8768ed326ff 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; @@ -55,8 +56,10 @@ public abstract class RContainerReference implements ObjectReference { public RContainerReference() { } + @NotQueryable protected abstract Container getOwner(); + @NotQueryable protected String getOwnerOid() { if (ownerOid == null && getOwner() != null) { ownerOid = getOwner().getOwnerOid(); @@ -64,6 +67,7 @@ protected String getOwnerOid() { return ownerOid; } + @NotQueryable protected Integer getOwnerId() { if (ownerId == null && getOwner() != null) { ownerId = getOwner().getId(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java index 4a2b2c97040..c57bb5d5eda 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.repo.sql.data.common.enums.RExclusionPolicy; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -72,6 +73,7 @@ public RExclusion(RObject owner) { @ForeignKey(name = "fk_exclusion_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java index 0af4e3aaa0f..ce7eded878b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java @@ -4,6 +4,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -52,11 +53,13 @@ public RTrigger(RObject owner) { @ForeignKey(name = "fk_trigger_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) + @NotQueryable public RObject getOwner() { return owner; } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + @NotQueryable public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); @@ -68,6 +71,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") + @NotQueryable public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java index 1015d37d3c1..872dc0633ef 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java @@ -4,6 +4,7 @@ import com.evolveum.midpoint.repo.sql.data.common.container.Container; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; @@ -47,6 +48,7 @@ public class RLookupTableRow implements Container { @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) @Override + @NotQueryable public RLookupTable getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java index 29d7670dbd2..d9361211401 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java @@ -25,8 +25,8 @@ * @author mederly */ public class DefinitionSearchResult { - T itemDefinition; // definition of the item itself - ItemPath remainder; // what has remained unresolved of the original search path + private T itemDefinition; // definition of the item itself + private ItemPath remainder; // what has remained unresolved of the original search path public DefinitionSearchResult(T itemDefinition, ItemPath remainder) { Validate.notNull(itemDefinition, "itemDefinition"); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java index c4e8343496c..f9f41e27264 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java @@ -22,13 +22,13 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.DefinitionPath; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; @@ -83,7 +83,7 @@ public String prepareJoins(ItemPath relativePath, String currentHqlPath, EntityD Definition definition = definitions.get(i); if (definition instanceof EntityDefinition) { EntityDefinition entityDef = (EntityDefinition) definition; - if (!entityDef.isEmbedded()) { + if (!entityDef.isEmbedded() || entityDef.isCollection()) { LOGGER.trace("Adding join for '{}' to context", entityDef.getJpaName()); currentHqlPath = addJoin(entityDef, currentHqlPath); } else { @@ -95,16 +95,11 @@ public String prepareJoins(ItemPath relativePath, String currentHqlPath, EntityD currentHqlPath = addJoin(definition, currentHqlPath); } break; - } else if (definition instanceof CollectionDefinition) { - LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); - currentHqlPath = addJoin(definition, currentHqlPath); - - // Because the next definition in the chain is the one that is referred to by this Collection - // (either property, reference or entity), we need to skip it: If it's entity, we have already - // joined it - and if it's property/reference, we would break the cycle even so - i++; - } else if (definition instanceof PropertyDefinition || definition instanceof ReferenceDefinition) { + if (definition.isCollection()) { + LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); + currentHqlPath = addJoin(definition, currentHqlPath); + } break; // quite redundant, as this is the last item in the chain } else { throw new QueryException("Not implemented yet: " + definition); @@ -123,8 +118,8 @@ protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); Condition condition = null; - if (joinedItemDefinition instanceof VirtualCollectionDefinition) { - VirtualCollectionDefinition vcd = (VirtualCollectionDefinition) joinedItemDefinition; + if (joinedItemDefinition.getCollectionSpecification() instanceof VirtualCollectionSpecification) { + VirtualCollectionSpecification vcd = (VirtualCollectionSpecification) joinedItemDefinition.getCollectionSpecification(); List conditions = new ArrayList<>(vcd.getAdditionalParams().length); for (VirtualQueryParam vqp : vcd.getAdditionalParams()) { // e.g. name = "assignmentOwner", type = RAssignmentOwner.class, value = "ABSTRACT_ROLE" @@ -174,7 +169,7 @@ public String addJoinAny(String currentHqlPath, String anyAssociationName, QName EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) String joinedItemJpaName = anyAssociationName; String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); + String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName); AndCondition conjunction = hibernateQuery.createAnd(); if (ownerType != null) { // null for assignment extensions @@ -193,11 +188,11 @@ public String addJoinAny(String currentHqlPath, String anyAssociationName, QName * * @param path Path to be found * @param clazz Kind of definition to be looked for - * @param complete Must the path be completely resolved? * @return Entity type definition + item definition, or null if nothing was found */ public ProperDefinitionSearchResult findProperDefinition(EntityDefinition baseEntityDefinition, - ItemPath path, Class clazz) throws QueryException { + ItemPath path, Class clazz) + throws QueryException { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); ProperDefinitionSearchResult candidateResult = null; @@ -217,6 +212,8 @@ public ProperDefinitionSearchResult findProperDefiniti } } } + LOGGER.trace("findProperDefinition: base={}, path={}, class={} -- returning {}", + baseEntityDefinition.getShortInfo(), path, clazz.getSimpleName(), candidateResult); return candidateResult; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java index 4ee27d817b1..81badc24024 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java @@ -44,5 +44,9 @@ public EntityDefinition getEntityDefinition() { return entityDefinition; } - + @Override + public String toString() { + return "ProperDefinitionSearchResult{" + + "entity=" + entityDefinition + ", item=" + getItemDefinition() + ", remainder=" + getRemainder() + "} "; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java index aa81f7cb374..5e34ddefa73 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -95,6 +95,9 @@ private QueryDefinitionRegistry2() { public static QueryDefinitionRegistry2 getInstance() { if (registry == null) { registry = new QueryDefinitionRegistry2(); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Registry:\n{}", registry.debugDump()); + } } return registry; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 722aa6f86ec..48ad62a817b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -39,10 +39,11 @@ import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -52,7 +53,6 @@ import com.evolveum.midpoint.repo.sql.query2.matcher.StringMatcher; import com.evolveum.midpoint.repo.sql.query2.restriction.AndRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.AnyPropertyRestriction; -import com.evolveum.midpoint.repo.sql.query2.restriction.CollectionRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.ExistsRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.InOidRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.NotRestriction; @@ -230,9 +230,9 @@ private Restriction findAndCreateRestrictionInternal(T } else if (filter instanceof RefFilter) { RefFilter refFilter = (RefFilter) filter; ItemPath path = refFilter.getFullPath(); - ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, Definition.class); + ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, ReferenceDefinition.class); if (searchResult == null) { - throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a queryable item"); + throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a reference item"); } return new ReferenceRestriction(context, refFilter, searchResult.getEntityDefinition(), parent, searchResult.getItemDefinition()); @@ -244,15 +244,6 @@ private Restriction findAndCreateRestrictionInternal(T if (propDefRes != null) { return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getItemDefinition()); } - ProperDefinitionSearchResult collDefRes = helper.findProperDefinition(baseEntityDefinition, path, CollectionDefinition.class); - if (collDefRes != null) { - Definition innerDef = collDefRes.getItemDefinition().getDefinition(); - if (innerDef instanceof PropertyDefinition) { - return new CollectionRestriction(context, valFilter, collDefRes.getEntityDefinition(), parent, (PropertyDefinition) innerDef); - } else { - throw new QueryException("ValueFilter is not supported for collections of items other than properties: " + innerDef); - } - } ProperDefinitionSearchResult anyDefRes = helper.findProperDefinition(baseEntityDefinition, path, AnyDefinition.class); if (anyDefRes != null) { if (ItemPath.containsSingleNameSegment(anyDefRes.getRemainder())) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java index 8d4b2d2fc6a..631b0a91352 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java @@ -27,7 +27,7 @@ public class AnyDefinition extends Definition { public AnyDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { - super(jaxbName, jaxbType, jpaName, jpaType); + super(jaxbName, jaxbType, jpaName, jpaType, null); } @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 442c10dac2d..a2afcf026aa 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -25,10 +25,6 @@ import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; -import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionDefinition; -import com.evolveum.midpoint.repo.sql.query.definition.VirtualProperty; -import com.evolveum.midpoint.repo.sql.query2.definition.VirtualPropertyDefinition; -import com.evolveum.midpoint.repo.sql.query.definition.VirtualReference; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.constants.ObjectTypes; @@ -62,14 +58,15 @@ public EntityDefinition parseObjectTypeClass(Class type) QName jaxbName = objectType.getQName(); Class jaxbType = objectType.getClassDefinition(); - EntityDefinition entityDefinition = new EntityDefinition(jaxbName, jaxbType, type.getSimpleName(), type); + EntityDefinition entityDefinition = new EntityDefinition(jaxbName, jaxbType, type.getSimpleName(), type, null); updateEntityDefinition(entityDefinition); return entityDefinition; } private void updateEntityDefinition(EntityDefinition entity) { - LOGGER.trace("### {}", new Object[]{entity.getJpaName()}); + LOGGER.trace("### {}", entity); + addVirtualDefinitions(entity); Method[] methods = entity.getJpaType().getMethods(); @@ -78,8 +75,9 @@ private void updateEntityDefinition(EntityDefinition entity) { for (Method method : methods) { String methodName = method.getName(); if (Modifier.isStatic(method.getModifiers()) || "getClass".equals(methodName) || - !methodName.startsWith("is") && !methodName.startsWith("get")) { - //it's not getter for property + (!methodName.startsWith("is") && !methodName.startsWith("get")) || + method.getAnnotation(NotQueryable.class) != null) { + //it's not getter for queryable property continue; } @@ -87,12 +85,12 @@ private void updateEntityDefinition(EntityDefinition entity) { continue; } - LOGGER.trace("# {}", new Object[]{methodName}); + LOGGER.trace("# {}", methodName); QName jaxbName = getJaxbName(method); Class jaxbType = getJaxbType(method); String jpaName = getJpaName(method); - Definition definition = createDefinition(jaxbName, jaxbType, jpaName, method); + Definition definition = createDefinition(jaxbName, jaxbType, jpaName, method, null); entity.addDefinition(definition); } } @@ -112,17 +110,17 @@ private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpa } QueryEntity qEntity = (QueryEntity) jpaType.getAnnotation(QueryEntity.class); - for (VirtualProperty property : qEntity.properties()) { - QName jaxbName = createQName(property.jaxbName()); - VirtualPropertyDefinition def = new VirtualPropertyDefinition(jaxbName, property.jaxbType(), - property.jpaName(), property.jpaType()); - def.setAdditionalParams(property.additionalParams()); - entityDef.addDefinition(def); - } - - for (VirtualReference reference : qEntity.references()) { - - } +// for (VirtualProperty property : qEntity.properties()) { +// QName jaxbName = createQName(property.jaxbName()); +// VirtualPropertyDefinition def = new VirtualPropertyDefinition(jaxbName, property.jaxbType(), +// property.jpaName(), property.jpaType()); +// def.setAdditionalParams(property.additionalParams()); +// entityDef.addDefinition(def); +// } +// +// for (VirtualReference reference : qEntity.references()) { +// +// } for (VirtualAny any : qEntity.anyElements()) { VirtualAnyDefinition def = new VirtualAnyDefinition( @@ -132,14 +130,12 @@ private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpa } for (VirtualCollection collection : qEntity.collections()) { - QName jaxbName = createQName(collection.jaxbName()); + VirtualCollectionSpecification colSpec = new VirtualCollectionSpecification(); + colSpec.setAdditionalParams(collection.additionalParams()); - VirtualCollectionDefinition def = new VirtualCollectionDefinition(jaxbName, - collection.jaxbType(), collection.jpaName(), collection.jpaType()); - def.setAdditionalParams(collection.additionalParams()); - updateCollectionDefinition(def, collection.collectionType(), jaxbName, collection.jpaName()); - - entityDef.addDefinition(def); + QName jaxbName = createQName(collection.jaxbName()); + Definition definition = createDefinition(jaxbName, collection.jaxbType(), collection.jpaName(), collection.collectionType(), colSpec); + entityDef.addDefinition(definition); } } @@ -147,61 +143,48 @@ private QName createQName(JaxbName name) { return new QName(name.namespace(), name.localPart()); } - private Definition createDefinition(QName jaxbName, Class jaxbType, String jpaName, AnnotatedElement object) { + private Definition createDefinition(QName jaxbName, Class jaxbType, String jpaName, AnnotatedElement object, CollectionSpecification collectionSpecification) { Class jpaType = (object instanceof Class) ? (Class) object : ((Method) object).getReturnType(); + if (Set.class.isAssignableFrom(jpaType)) { + if (collectionSpecification != null) { + throw new IllegalStateException("Collection within collection is not supported: jaxbName=" + + jaxbName + ", jaxbType=" + jaxbType + ", jpaName=" + jpaName + ", object=" + object); + } + collectionSpecification = new CollectionSpecification(); + if (object instanceof Method) { + Method method = (Method) object; + ParameterizedType type = (ParameterizedType) method.getGenericReturnType(); + Class clazz = (Class) type.getActualTypeArguments()[0]; + QName realJaxbName = getJaxbName(method); + Class realJaxbType = getJaxbType(clazz); + String realJpaName = getJpaName(method); + return createDefinition(realJaxbName, realJaxbType, realJpaName, clazz, collectionSpecification); + } else { + Class clazz = (Class) object; + Class realJaxbType = getJaxbType(clazz); + return createDefinition(jaxbName, realJaxbType, jpaName, clazz, collectionSpecification); + } + } + Definition definition; if (ObjectReference.class.isAssignableFrom(jpaType)) { - ReferenceDefinition refDef = new ReferenceDefinition(jaxbName, jaxbType, jpaName, jpaType); + ReferenceDefinition refDef = new ReferenceDefinition(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); definition = updateReferenceDefinition(refDef, object); } else if (RAssignmentExtension.class.isAssignableFrom(jpaType)) { definition = new AnyDefinition(jaxbName, jaxbType, jpaName, jpaType); - } else if (Set.class.isAssignableFrom(jpaType)) { - CollectionDefinition collDef = new CollectionDefinition(jaxbName, jaxbType, jpaName, jpaType); - updateCollectionDefinition(collDef, object, null, null); - definition = collDef; } else if (isEntity(object)) { - EntityDefinition entityDef = new EntityDefinition(jaxbName, jaxbType, jpaName, jpaType); - if ("com.evolveum.midpoint.repo.sql.data.common.embedded".equals(jpaType.getPackage().getName())) { - updateEntityDefinition(entityDef); - } + EntityDefinition entityDef = new EntityDefinition(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); + updateEntityDefinition(entityDef); definition = entityDef; } else { - PropertyDefinition propDef = new PropertyDefinition(jaxbName, jaxbType, jpaName, jpaType); + PropertyDefinition propDef = new PropertyDefinition(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); definition = updatePropertyDefinition(propDef, object); } return definition; } - private CollectionDefinition updateCollectionDefinition(CollectionDefinition definition, AnnotatedElement object, - QName jaxbName, String jpaName) { - Definition collDef; - if (object instanceof Method) { - Method method = (Method) object; - ParameterizedType type = (ParameterizedType) method.getGenericReturnType(); - Class clazz = (Class) type.getActualTypeArguments()[0]; - - QName realJaxbName = getJaxbName(method); - Class jaxbType = getJaxbType(clazz); - String realJpaName = getJpaName(method); - collDef = createDefinition(realJaxbName, jaxbType, realJpaName, clazz); - } else { - Class clazz = (Class) object; - - Class jaxbType = getJaxbType(clazz); - collDef = createDefinition(jaxbName, jaxbType, jpaName, clazz); - } - - if (collDef instanceof EntityDefinition) { - updateEntityDefinition((EntityDefinition) collDef); - } - - definition.setDefinition(collDef); - - return definition; - } - private boolean isEntity(AnnotatedElement object) { Class type = (object instanceof Class) ? (Class) object : ((Method) object).getReturnType(); if (RPolyString.class.isAssignableFrom(type)) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java deleted file mode 100644 index 99d04f6a149..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionDefinition.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.Holder; - -import javax.xml.namespace.QName; - -/** - * @author lazyman - */ -public class CollectionDefinition extends Definition { - - private Definition definition; - - public CollectionDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { - super(jaxbName, jaxbType, propertyName, propertyType); - } - - public Definition getDefinition() { - return definition; - } - - void setDefinition(Definition definition) { - this.definition = definition; - } - - @Override - public DefinitionSearchResult nextDefinition(ItemPath path) { - return new DefinitionSearchResult(definition, path); - } - - @Override - protected void toStringExtended(StringBuilder builder) { - String def = definition != null ? definition.toString() : null; - builder.append(", def=").append(def); - } - - @Override - public String debugDump(int indent) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < indent; i++) { - sb.append(DebugDumpable.INDENT_STRING); - } - sb.append(toString()); - - sb.append('\n'); - String def = null; - if (definition == null) { - for (int i = 0; i < indent + 1; i++) { - sb.append(DebugDumpable.INDENT_STRING); - } - } else { - def = definition.debugDump(indent + 1); - } - sb.append(def); - - return sb.toString(); - } - - @Override - protected String getDebugDumpClassName() { - return "Col"; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java new file mode 100644 index 00000000000..617ec281b43 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.Holder; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class CollectionSpecification { + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java index 6aab7313421..73c2b5855ba 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java @@ -39,11 +39,14 @@ public abstract class Definition implements DebugDumpable { private String jpaName; private Class jpaType; - public Definition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { + private CollectionSpecification collectionSpecification; + + public Definition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { this.jaxbName = jaxbName; this.jaxbType = jaxbType; this.jpaName = jpaName; this.jpaType = jpaType; + this.collectionSpecification = collectionSpecification; } public QName getJaxbName() { @@ -62,22 +65,7 @@ public Class getJpaType() { return jpaType; } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(getDebugDumpClassName()); - builder.append('{'); - builder.append("jaxbN=").append(dumpQName(jaxbName)); - builder.append(", jaxbT=").append((jaxbType != null ? jaxbType.getSimpleName() : "")); - builder.append(", jpaN=").append(jpaName); - builder.append(", jpaT=").append((jpaType != null ? jpaType.getSimpleName() : "")); - toStringExtended(builder); - builder.append('}'); - - return builder.toString(); - } - - protected void toStringExtended(StringBuilder builder) { + protected void debugDumpExtended(StringBuilder builder, int indent) { } @@ -108,7 +96,18 @@ public String debugDump(int indent) { for (int i = 0; i < indent; i++) { sb.append(DebugDumpable.INDENT_STRING); } - sb.append(toString()); + sb.append(getDebugDumpClassName()); + sb.append('{'); + sb.append("jaxbN=").append(dumpQName(jaxbName)); + sb.append(", jaxbT=").append((jaxbType != null ? jaxbType.getSimpleName() : "")); + sb.append(", jpaN=").append(jpaName); + sb.append(", jpaT=").append((jpaType != null ? jpaType.getSimpleName() : "")); + if (collectionSpecification != null) { + sb.append(", coll=").append(collectionSpecification); // TODO + } + debugDumpExtended(sb, indent); + sb.append('}'); + return sb.toString(); } @@ -202,6 +201,20 @@ public DefinitionPath translatePath(ItemPath itemPath) { } public String getShortInfo() { - return getDebugDumpClassName() + ":" + DebugUtil.formatElementName(getJaxbName()) + ":" + getJpaName(); + return getDebugDumpClassName() + + (collectionSpecification != null ? "[]" : "") + + ":" + DebugUtil.formatElementName(getJaxbName()) + ":" + getJpaName(); + } + + public String toString() { + return getShortInfo(); + } + + public boolean isCollection() { + return collectionSpecification != null; + } + + public CollectionSpecification getCollectionSpecification() { + return collectionSpecification; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java index 15dd2fbf1ad..592dcc39a91 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java @@ -42,8 +42,6 @@ private int getType(Definition def) { return 1; } else if (def instanceof ReferenceDefinition) { return 2; - } else if (def instanceof CollectionDefinition) { - return 3; } else if (def instanceof AnyDefinition) { return 4; } else if (def instanceof EntityDefinition) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java index 87f54440ccf..149b372b05f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java @@ -18,10 +18,9 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.repo.sql.query.restriction.PathTranslation; import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.Holder; +import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; @@ -46,8 +45,8 @@ public class EntityDefinition extends Definition { private boolean embedded; private EntityDefinition superclassDefinition; - public EntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { - super(jaxbName, jaxbType, jpaName, jpaType); + public EntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { + super(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); Validate.notNull(jaxbName, "jaxbName"); Validate.notNull(jaxbType, "jaxbType"); Validate.notNull(jpaName, "jpaName"); @@ -83,35 +82,16 @@ public void addDefinition(Definition definition) { } @Override - protected void toStringExtended(StringBuilder builder) { + protected void debugDumpExtended(StringBuilder builder, int indent) { builder.append(", embedded=").append(isEmbedded()); - builder.append(", definitions=["); + builder.append(", definitions=\n"); List definitions = getDefinitions(); for (Definition definition : definitions) { - builder.append(definition.getDebugDumpClassName()); - builder.append('(').append(dumpQName(definition.getJaxbName())).append(')'); + builder.append(definition.debugDump(indent+1)); + builder.append('\n'); } - builder.append(']'); - } - - @Override - public String debugDump(int indent) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < indent; i++) { - sb.append(DebugDumpable.INDENT_STRING); - } - sb.append(toString()); - - List definitions = getDefinitions(); - for (Definition definition : definitions) { - sb.append(definition.debugDump(indent + 1)); - if (definitions.indexOf(definition) != definitions.size() - 1) { - sb.append('\n'); - } - } - - return sb.toString(); + DebugUtil.indentDebugDump(builder, indent); // before final '}' } @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java new file mode 100644 index 00000000000..368714b2dd3 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author mederly + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface NotQueryable { + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java index f69255fe7ff..a5fdfb35ae4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java @@ -33,8 +33,8 @@ public class PropertyDefinition extends Definition { //jpa special things private boolean indexed; - public PropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { - super(jaxbName, jaxbType, propertyName, propertyType); + public PropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType, CollectionSpecification collectionSpecification) { + super(jaxbName, jaxbType, propertyName, propertyType, collectionSpecification); } public boolean isLob() { @@ -66,7 +66,7 @@ void setIndexed(boolean indexed) { } @Override - protected void toStringExtended(StringBuilder builder) { + protected void debugDumpExtended(StringBuilder builder, int indent) { builder.append(", lob=").append(isLob()); builder.append(", enumerated=").append(isEnumerated()); builder.append(", indexed=").append(isIndexed()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java index c3bc89b04db..42286ac9c19 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java @@ -28,8 +28,8 @@ public class ReferenceDefinition extends Definition { private boolean embedded; - public ReferenceDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { - super(jaxbName, jaxbType, jpaName, jpaType); + public ReferenceDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { + super(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); } public boolean isEmbedded() { @@ -41,7 +41,7 @@ void setEmbedded(boolean embedded) { } @Override - protected void toStringExtended(StringBuilder builder) { + protected void debugDumpExtended(StringBuilder builder, int indent) { builder.append(", embedded=").append(isEmbedded()); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java similarity index 66% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java index c799b8421ad..e50ae3b92c8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java @@ -23,12 +23,11 @@ /** * @author lazyman */ -public class VirtualCollectionDefinition extends CollectionDefinition { +public class VirtualCollectionSpecification extends CollectionSpecification { private VirtualQueryParam[] additionalParams; - public VirtualCollectionDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { - super(jaxbName, jaxbType, propertyName, propertyType); + public VirtualCollectionSpecification() { } public VirtualQueryParam[] getAdditionalParams() { @@ -39,15 +38,4 @@ void setAdditionalParams(VirtualQueryParam[] additionalParams) { this.additionalParams = additionalParams; } - @Override - protected void toStringExtended(StringBuilder builder) { - super.toStringExtended(builder); - - builder.append(", params=").append(additionalParams.length); - } - - @Override - protected String getDebugDumpClassName() { - return "VirtualCol"; - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java index 258f934cd13..014dafc5f92 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java @@ -27,8 +27,8 @@ public class VirtualEntityDefinition extends EntityDefinition { private VirtualQueryParam[] additionalParams; - public VirtualEntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { - super(jaxbName, jaxbType, jpaName, jpaType); + public VirtualEntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { + super(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); } public VirtualQueryParam[] getAdditionalParams() { @@ -40,8 +40,8 @@ void setAdditionalParams(VirtualQueryParam[] additionalParams) { } @Override - protected void toStringExtended(StringBuilder builder) { - super.toStringExtended(builder); + protected void debugDumpExtended(StringBuilder builder, int indent) { + super.debugDumpExtended(builder, indent); builder.append(", params=").append(additionalParams.length); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java index 7bb3666f5c5..d5f03ea3baa 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java @@ -27,8 +27,8 @@ public class VirtualPropertyDefinition extends PropertyDefinition { private VirtualQueryParam[] additionalParams; - public VirtualPropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType) { - super(jaxbName, jaxbType, propertyName, propertyType); + public VirtualPropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType, CollectionSpecification collectionSpecification) { + super(jaxbName, jaxbType, propertyName, propertyType, collectionSpecification); } public VirtualQueryParam[] getAdditionalParams() { @@ -40,8 +40,8 @@ void setAdditionalParams(VirtualQueryParam[] additionalParams) { } @Override - protected void toStringExtended(StringBuilder builder) { - super.toStringExtended(builder); + protected void debugDumpExtended(StringBuilder builder, int indent) { + super.debugDumpExtended(builder, indent); builder.append(", params=").append(additionalParams.length); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index 1050b444442..9c59af12c32 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -154,16 +154,16 @@ public EntityReference createItemSpecification(EntityDefinition entityDef) { } public String createAlias(Definition def) { - return createAlias(def.getJpaName(), def instanceof EntityDefinition); + return createAlias(def.getJpaName()); } private static final int LIMIT = 100; - public String createAlias(String name, boolean isEntity) { + public String createAlias(String name) { String prefix; - //we want to skip 'R' prefix for entity definition names - int prefixIndex = isEntity ? 1 : 0; + //we want to skip 'R' prefix for entity definition names (a bit of hack) + int prefixIndex = name.startsWith("R") ? 1 : 0; prefix = Character.toString(name.charAt(prefixIndex)).toLowerCase(); int index = 2; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java deleted file mode 100644 index 03f3724267b..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/CollectionRestriction.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.restriction; - -import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import org.apache.commons.lang.Validate; - -/** - * @author lazyman - */ -public class CollectionRestriction extends ItemValueRestriction { - - private PropertyDefinition collectionPropertyDefinition; - - public CollectionRestriction(InterpretationContext context, ValueFilter filter, EntityDefinition baseEntityDefinition, - Restriction parent, PropertyDefinition collectionPropertyDefinition) { - super(context, filter, baseEntityDefinition, parent); - Validate.notNull(collectionPropertyDefinition, "collectionPropertyDefinition"); - this.collectionPropertyDefinition = collectionPropertyDefinition; - } - - - @Override - public Condition interpretInternal(String hqlPath) throws QueryException { - Object value = getValueFromFilter(filter, collectionPropertyDefinition); - - return createCondition(hqlPath, value, filter); - - // TODO what about not-null ? - } - -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java index b15967612a0..e8e59a419eb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java @@ -52,7 +52,7 @@ public ExistsRestriction(InterpretationContext context, ExistsFilter filter, Ent @Override public Condition interpret() throws QueryException { - baseHqlPathForChildren = getHelper().prepareJoins(filter.getFullPath(), parent.getBaseHqlPathForChildren(), baseEntityDefinition); + baseHqlPathForChildren = getHelper().prepareJoins(filter.getFullPath(), getBaseHqlPath(), baseEntityDefinition); InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index 2f513a4620d..c3413e7cda6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -49,7 +49,12 @@ public Condition interpretInternal(String hqlPath) throws QueryException { throw new QueryException("Can't query based on clob property value '" + propertyDefinition + "'."); } - String propertyFullName = hqlPath + "." + propertyDefinition.getJpaName(); + String propertyFullName; + if (propertyDefinition.isCollection()) { + propertyFullName = hqlPath; + } else { + propertyFullName = hqlPath + "." + propertyDefinition.getJpaName(); + } Object value = getValueFromFilter(filter, propertyDefinition); Condition condition = createCondition(propertyFullName, value, filter); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index 638872dd77b..1bc1e951fd6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -19,13 +19,11 @@ import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.CollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; @@ -77,12 +75,10 @@ public Condition interpretInternal(String hqlPath) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String propertyFullNamePrefix; - if (itemDefinition instanceof CollectionDefinition) { + if (itemDefinition.isCollection()) { propertyFullNamePrefix = hqlPath + "."; - } else if (itemDefinition instanceof ReferenceDefinition) { - propertyFullNamePrefix = hqlPath + "." + itemDefinition.getJpaName() + "."; } else { - throw new IllegalStateException("Unexpected kind of Definition while processing ReferenceRestriction: " + itemDefinition); + propertyFullNamePrefix = hqlPath + "." + itemDefinition.getJpaName() + "."; } String refValueOid = null; From 44dac1540582c3a207aadee751467ff5efe64596 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 25 Nov 2015 14:36:28 +0100 Subject: [PATCH 015/116] Fixed MID-2701: SelfService Home - Task not found --- .../com/evolveum/midpoint/web/page/self/PageSelfDashboard.java | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java index 766f5e9d083..cb66ce88dde 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java @@ -225,6 +225,7 @@ private CallableResult> loadMyRequests() { shadowTask = getTaskManager().getTask(shadowTaskOid, result); } catch (ObjectNotFoundException e) { // task is already deleted, no problem here + result.muteLastSubresultError(); } } From c8f57e931c4dfa26c2e5d676517f5f5d27556ef0 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 25 Nov 2015 15:40:41 +0100 Subject: [PATCH 016/116] Working on AccCertCase queries - interim commit. --- .../repo/sql/QueryInterpreter2Test.java | 167 +++++++++++------- .../repo/sql/SqlRepositoryServiceImpl.java | 155 +++++++++------- .../container/RAccessCertificationCase.java | 5 + .../sql/query2/InterpretationContext.java | 7 +- .../sql/query2/QueryDefinitionRegistry2.java | 25 ++- .../repo/sql/query2/QueryEngine2.java | 3 +- .../repo/sql/query2/QueryInterpreter2.java | 7 +- .../definition/ClassDefinitionParser.java | 6 +- .../query2/definition/EntityDefinition.java | 2 +- 9 files changed, 239 insertions(+), 138 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 529f3173125..3126d1f7652 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismObject; @@ -37,6 +38,7 @@ import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.prism.query.OrgFilter; +import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.TypeFilter; @@ -51,12 +53,14 @@ import com.evolveum.midpoint.schema.MidPointPrismContextFactory; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; @@ -75,6 +79,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.prism.xml.ns._public.query_3.QueryType; import org.apache.commons.lang.StringUtils; import org.hibernate.Session; import org.hibernate.criterion.ProjectionList; @@ -150,7 +155,7 @@ public void test001QueryNameNorm() throws Exception { "where\n" + " u.name.norm = :norm"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -176,7 +181,7 @@ public void test002QueryNameOrig() throws Exception { "where\n" + " u.name.orig = :orig"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -202,7 +207,7 @@ public void test003QueryNameStrict() throws Exception { "where\n" + " ( u.name.orig = :orig and u.name.norm = :norm )"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -229,7 +234,7 @@ public void test010QueryOrganizationNorm() throws Exception { "where\n" + " o.norm = :norm"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -267,7 +272,7 @@ public void test011QueryOrganizationOrig() throws Exception { "where\n" + " o.orig = :orig"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -294,7 +299,7 @@ public void test012QueryOrganizationStrict() throws Exception { "where\n" + " ( o.orig = :orig and o.norm = :norm )"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -324,7 +329,7 @@ public void test020QueryTwoOrganizationsNormAnd() throws Exception { "where\n" + " ( o.norm = :norm and o2.norm = :norm2 )"; - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -358,7 +363,7 @@ public void test021QueryTwoOrganizationsStrictOr() throws Exception { // NOTE: this could be implemented more efficiently by using only one join... or the query itself can be formulated // via In filter (when available) or ForValue filter (also, when available) - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -384,7 +389,7 @@ public void test025QueryOrganizationOrigPolymorphic() throws Exception { "where\n" + " o2.orig = :orig"; - String real = getInterpretedQuery(session, ObjectType.class, query); + String real = getInterpretedQuery2(session, ObjectType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -410,7 +415,7 @@ public void test030QueryTaskDependent() throws Exception { "where\n" + " d = :d"; - String real = getInterpretedQuery(session, TaskType.class, query); + String real = getInterpretedQuery2(session, TaskType.class, query); assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -426,7 +431,7 @@ public void test040QueryClob() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); //should throw exception, because description is lob and can't be queried - getInterpretedQuery(session, UserType.class, query); + getInterpretedQuery2(session, UserType.class, query); } finally { close(session); } @@ -442,7 +447,7 @@ public void test050QueryEnum() throws Exception { ObjectFilter filter = EqualFilter.createEqual(TaskType.F_EXECUTION_STATUS, TaskType.class, prismContext, null, TaskExecutionStatusType.WAITING); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, TaskType.class, query); + String real = getInterpretedQuery2(session, TaskType.class, query); String expected = "select\n" + " t.fullObject,\n" + @@ -472,7 +477,7 @@ public void test060QueryEnabled() throws Exception { * ==> from RUser u where u.activation.administrativeStatus = com.evolveum.midpoint.repo.sql.data.common.enums.RActivationStatus.ENABLED */ - String real = getInterpretedQuery(session, UserType.class, + String real = getInterpretedQuery2(session, UserType.class, new File(TEST_DIR, "query-user-by-enabled.xml")); String expected = "select\n" + @@ -508,7 +513,7 @@ public void test070QueryGenericLong() throws Exception { * l.value = 123 */ - String real = getInterpretedQuery(session, GenericObjectType.class, + String real = getInterpretedQuery2(session, GenericObjectType.class, new File(TEST_DIR, "query-and-generic.xml")); String expected = "select\n" + @@ -529,7 +534,7 @@ public void test070QueryGenericLong() throws Exception { public void test072QueryAccountByAttribute() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, ShadowType.class, + String real = getInterpretedQuery2(session, ShadowType.class, new File(TEST_DIR, "query-account-by-attribute.xml")); String expected = "select\n" + " s.fullObject, s.stringsCount, s.longsCount, s.datesCount, s.referencesCount, s.polysCount, s.booleansCount\n" + @@ -548,7 +553,7 @@ public void test072QueryAccountByAttribute() throws Exception { public void test074QueryAccountByAttributeAndExtensionValue() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, ShadowType.class, + String real = getInterpretedQuery2(session, ShadowType.class, new File(TEST_DIR, "query-account-by-attribute-and-extension-value.xml")); String expected = "select\n" + " s.fullObject, s.stringsCount, s.longsCount, s.datesCount, s.referencesCount, s.polysCount, s.booleansCount\n" + @@ -587,7 +592,7 @@ public void test076QueryOrComposite() throws Exception { * * [If we used AND instead of OR, this SHOULD BE left join r.strings s1, left join r.strings s2] */ - String real = getInterpretedQuery(session, ShadowType.class, + String real = getInterpretedQuery2(session, ShadowType.class, new File(TEST_DIR, "query-or-composite.xml")); String expected = "select\n" + @@ -640,7 +645,7 @@ public void test080QueryExistsAssignment() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); //assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -664,7 +669,7 @@ public void test100QueryObjectByName() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); - String real = getInterpretedQuery(session, ObjectType.class, query); + String real = getInterpretedQuery2(session, ObjectType.class, query); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -692,7 +697,7 @@ public void test110QueryUserByFullName() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, UserType.class, + String real = getInterpretedQuery2(session, UserType.class, new File(TEST_DIR, "query-user-by-fullName.xml")); String expected = "select\n" + " u.fullObject,\n" + @@ -717,7 +722,7 @@ public void test112QueryUserSubstringFullName() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, UserType.class, + String real = getInterpretedQuery2(session, UserType.class, new File(TEST_DIR, "query-user-substring-fullName.xml")); String expected = "select\n" + " u.fullObject,\n" + @@ -742,7 +747,7 @@ public void test114QueryUserByName() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, UserType.class, + String real = getInterpretedQuery2(session, UserType.class, new File(TEST_DIR, "query-user-by-name.xml")); String expected = "select\n" + " u.fullObject,\n" + @@ -767,7 +772,7 @@ public void test120QueryConnectorByType() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, ConnectorType.class, + String real = getInterpretedQuery2(session, ConnectorType.class, new File(TEST_DIR, "query-connector-by-type.xml")); String expected = "select\n" + " c.fullObject,\n" + @@ -791,7 +796,7 @@ public void test120QueryConnectorByType() throws Exception { public void test130QueryAccountByAttributesAndResourceRef() throws Exception { Session session = open(); try { - String real = getInterpretedQuery(session, ShadowType.class, + String real = getInterpretedQuery2(session, ShadowType.class, new File(TEST_DIR, "query-account-by-attributes-and-resource-ref.xml")); String expected = "select\n" + " s.fullObject,\n" + @@ -830,7 +835,7 @@ public void test140QueryUserAccountRef() throws Exception { * l.targetOid = '123' and l.relation = '#' */ RefFilter filter = RefFilter.createReferenceEqual(UserType.F_LINK_REF, UserType.class, prismContext, "123"); - String real = getInterpretedQuery(session, UserType.class, ObjectQuery.createObjectQuery(filter)); + String real = getInterpretedQuery2(session, UserType.class, ObjectQuery.createObjectQuery(filter)); String expected = "select\n" + " u.fullObject,\n" + @@ -873,7 +878,7 @@ public void test150QueryUserAssignmentTargetRef() throws Exception { RefFilter filter = RefFilter.createReferenceEqual( new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_TARGET_REF), UserType.class, prismContext, ort.asReferenceValue()); - String real = getInterpretedQuery(session, UserType.class, ObjectQuery.createObjectQuery(filter)); + String real = getInterpretedQuery2(session, UserType.class, ObjectQuery.createObjectQuery(filter)); String expected = "select\n" + " u.fullObject,\n" + " u.stringsCount,\n" + @@ -911,7 +916,7 @@ public void test160QueryTrigger() throws Exception { ItemPath triggerPath = new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP); ObjectFilter filter = LessFilter.createLess(triggerPath, objectDef, thisScanTimestamp, true); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, ObjectType.class, query); + String real = getInterpretedQuery2(session, ObjectType.class, query); String expected = "select\n" + " o.fullObject,\n" + @@ -942,7 +947,7 @@ public void test170QueryAssignmentActivationAdministrativeStatus() throws Except ItemPath activationPath = new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); ObjectFilter filter = EqualFilter.createEqual(activationPath, objectDef, ActivationStatusType.ENABLED); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); String expected = "select\n" + " u.fullObject,\n" + @@ -980,7 +985,7 @@ public void test180QueryInducementActivationAdministrativeStatus() throws Except ItemPath activationPath = new ItemPath(RoleType.F_INDUCEMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); ObjectFilter filter = EqualFilter.createEqual(activationPath, objectDef, ActivationStatusType.ENABLED); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, RoleType.class, query); + String real = getInterpretedQuery2(session, RoleType.class, query); String expected = "select\n" + " r.fullObject,\n" + @@ -1023,7 +1028,7 @@ public void test182QueryInducementAndAssignmentActivationAdministrativeStatus() ObjectFilter filter2 = EqualFilter.createEqual(activationPath2, objectDef, ActivationStatusType.ENABLED); ObjectQuery query = ObjectQuery.createObjectQuery(OrFilter.createOr(filter1, filter2)); - String real = getInterpretedQuery(session, RoleType.class, query); + String real = getInterpretedQuery2(session, RoleType.class, query); String expected = "select\n" + " r.fullObject,\n" + @@ -1070,7 +1075,7 @@ public void test190QueryUserByActivationDouble() throws Exception { XmlTypeConverter.createXMLGregorianCalendar(NOW.getTime())); ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(filter1, filter2)); - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -1105,7 +1110,7 @@ public void test200QueryTriggerTimestampDoubleWrong() throws Exception { LOGGER.info(and.debugDump()); ObjectQuery query = ObjectQuery.createObjectQuery(and); - String real = getInterpretedQuery(session, ObjectType.class, query); + String real = getInterpretedQuery2(session, ObjectType.class, query); // correct translation but the filter is wrong: we need to point to THE SAME timestamp -> i.e. ForValue should be used here String expected = "select\n" + @@ -1163,7 +1168,7 @@ public void test300CountObjectOrderByName() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); - String real = getInterpretedQuery(session, UserType.class, query, true); + String real = getInterpretedQuery2(session, UserType.class, query, true); String expected = "select\n" + " count(*)\n" + "from\n" + @@ -1187,7 +1192,7 @@ public void test310CountObjectOrderByNameWithoutFilter() throws Exception { ObjectPaging paging = ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING); ObjectQuery query = ObjectQuery.createObjectQuery(null, paging); - String real = getInterpretedQuery(session, ObjectType.class, query, true); + String real = getInterpretedQuery2(session, ObjectType.class, query, true); String expected = "select\n" + " count(*)\n" + "from\n" + @@ -1213,7 +1218,7 @@ public void test320CountTaskOrderByName() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); query.setPaging(ObjectPaging.createPaging(null, null, TaskType.F_NAME, OrderDirection.ASCENDING)); - String real = getInterpretedQuery(session, TaskType.class, query, true); + String real = getInterpretedQuery2(session, TaskType.class, query, true); String expected = "select\n" + " count(*)\n" + "from\n" + @@ -1233,7 +1238,7 @@ public void test330InOidTest() throws Exception { InOidFilter filter = InOidFilter.createInOid(Arrays.asList("1", "2")); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, ObjectType.class, query, false); + String real = getInterpretedQuery2(session, ObjectType.class, query, false); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1263,7 +1268,7 @@ public void test340QueryOrgTreeFindOrgs() throws Exception { objectQuery.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); objectQuery.setUseNewQueryInterpreter(true); - String real = getInterpretedQuery(session, OrgType.class, objectQuery); + String real = getInterpretedQuery2(session, OrgType.class, objectQuery); OperationResult result = new OperationResult("query org structure"); repositoryService.searchObjects(OrgType.class, objectQuery, null, result); @@ -1340,7 +1345,7 @@ public void test400ActivationQueryWrong() throws Exception { Session session = open(); try { ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, UserType.class, query, false); + String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + " u.fullObject,\n" + @@ -1395,7 +1400,7 @@ public void test405ActivationQueryCorrect() throws Exception { Session session = open(); try { ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, UserType.class, query, false); + String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + " u.fullObject,\n" + @@ -1462,7 +1467,7 @@ public void test410ActivationQueryWrong() throws Exception { Session session = open(); try { ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, UserType.class, query, false); + String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + " u.fullObject,\n" + @@ -1549,7 +1554,7 @@ public void test415ActivationQueryCorrect() throws Exception { Session session = open(); try { ObjectQuery query = ObjectQuery.createObjectQuery(filter); - String real = getInterpretedQuery(session, UserType.class, query, false); + String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + " u.fullObject,\n" + @@ -1659,7 +1664,7 @@ public void test510QueryNameAndOrg() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(eqFilter, orgFilter)); query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); - String real = getInterpretedQuery(session, UserType.class, query); + String real = getInterpretedQuery2(session, UserType.class, query); String expected = "select\n" + " u.fullObject,\n" + @@ -1709,7 +1714,7 @@ public void test510QueryNameAndOrg() throws Exception { // )); // query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); // -// String real = getInterpretedQuery(session, ObjectType.class, query); +// String real = getInterpretedQuery2(session, ObjectType.class, query); // // LOGGER.info("real query>\n{}", new Object[]{real}); // } finally { @@ -1728,7 +1733,7 @@ public void test530queryUserSubstringName() throws Exception { ObjectQuery objectQuery = ObjectQuery.createObjectQuery(substring); objectQuery.setUseNewQueryInterpreter(true); - String real = getInterpretedQuery(session, ObjectType.class, objectQuery); + String real = getInterpretedQuery2(session, ObjectType.class, objectQuery); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1765,7 +1770,7 @@ public void test540queryObjectClassTypeUser() throws Exception { try { TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, null); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1791,7 +1796,7 @@ public void test550queryObjectClassTypeAbstractRole() throws Exception { try { TypeFilter type = TypeFilter.createType(AbstractRoleType.COMPLEX_TYPE, null); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1822,7 +1827,7 @@ public void test560queryMetadataTimestamp() throws Exception { new ItemPath(ReportOutputType.F_METADATA, MetadataType.F_CREATE_TIMESTAMP), ReportOutputType.class, prismContext, timeXml, true); - String real = getInterpretedQuery(session, ReportOutputType.class, ObjectQuery.createObjectQuery(less)); + String real = getInterpretedQuery2(session, ReportOutputType.class, ObjectQuery.createObjectQuery(less)); String expected = "select\n" + " r.fullObject,\n" + " r.stringsCount,\n" + @@ -1863,7 +1868,7 @@ public void test570queryObjectypeByTypeUserAndLocality() throws Exception { new PolyString("Caribbean", "caribbean")); TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, eq); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1928,7 +1933,7 @@ public void test575QueryObjectypeByTypeOrgAndLocality() throws Exception { new PolyString("Caribbean", "caribbean")); TypeFilter type = TypeFilter.createType(OrgType.COMPLEX_TYPE, eq); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1963,7 +1968,7 @@ public void test580QueryObjectypeByTypeAndExtensionAttribute() throws Exception UserType.class, prismContext, "some weapon name"); TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, eq); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -1994,7 +1999,7 @@ public void test590QueryObjectypeByTypeAndReference() throws Exception { RefFilter ref = RefFilter.createReferenceEqual(UserType.F_LINK_REF, UserType.class, prismContext, "123"); TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, ref); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(type)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -2062,7 +2067,7 @@ public void test600QueryObjectypeByTypeComplex() throws Exception { OrFilter or = OrFilter.createOr(type1, type2, type3); - String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(or)); + String real = getInterpretedQuery2(session, ObjectType.class, ObjectQuery.createObjectQuery(or)); String expected = "select\n" + " o.fullObject,\n" + " o.stringsCount,\n" + @@ -2109,7 +2114,7 @@ public void test610QueryGenericClob() throws Exception { new ItemPath(ObjectType.F_EXTENSION, new QName("http://example.com/p", "locations")), GenericObjectType.class, prismContext, null); - getInterpretedQuery(session, GenericObjectType.class, ObjectQuery.createObjectQuery(eq)); + getInterpretedQuery2(session, GenericObjectType.class, ObjectQuery.createObjectQuery(eq)); } catch (QueryException ex) { LOGGER.info("Exception", ex); throw ex; @@ -2126,7 +2131,7 @@ public void test620QueryGenericString() throws Exception { new ItemPath(ObjectType.F_EXTENSION, new QName("http://example.com/p", "stringType")), GenericObjectType.class, prismContext, "asdf"); - String real = getInterpretedQuery(session, GenericObjectType.class, ObjectQuery.createObjectQuery(eq)); + String real = getInterpretedQuery2(session, GenericObjectType.class, ObjectQuery.createObjectQuery(eq)); String expected = "select\n" + " g.fullObject,\n" + " g.stringsCount,\n" + @@ -2180,7 +2185,7 @@ public void test620QueryGenericString() throws Exception { // List l = rQuery.list(); // LOGGER.info(">>>>>>>>asdfasdfasdfasdf{}",l.size()); // -// String real = getInterpretedQuery(session, ShadowType.class, query); +// String real = getInterpretedQuery2(session, ShadowType.class, query); // // LOGGER.info("exp. query>\n{}\nreal query>\n{}", new Object[]{expected, real}); // AssertJUnit.assertEquals(expected, real); @@ -2200,7 +2205,7 @@ public void test630QueryGenericBoolean() throws Exception { ObjectQuery objectQuery = ObjectQuery.createObjectQuery(eq); objectQuery.setUseNewQueryInterpreter(true); - String real = getInterpretedQuery(session, GenericObjectType.class, objectQuery); + String real = getInterpretedQuery2(session, GenericObjectType.class, objectQuery); String expected = "select\n" + " g.fullObject,\n" + " g.stringsCount,\n" + @@ -2256,7 +2261,7 @@ public void test640queryAssignmentExtensionBoolean() throws Exception { ObjectQuery objectQuery = ObjectQuery.createObjectQuery(eq); objectQuery.setUseNewQueryInterpreter(true); - String real = getInterpretedQuery(session, UserType.class, objectQuery); + String real = getInterpretedQuery2(session, UserType.class, objectQuery); String expected = "select\n" + " u.fullObject,\n" + " u.stringsCount,\n" + @@ -2296,10 +2301,52 @@ public void test640queryAssignmentExtensionBoolean() throws Exception { } } - protected String getInterpretedQuery(Session session, Class type, ObjectQuery query, - boolean interpretCount) throws Exception { + @Test + public void test700QueryCertCaseAll() throws Exception { + Session session = open(); + try { + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, (ObjectQuery) null, false); + +// assertEqualsIgnoreWhitespace(expected, real); + + } finally { + close(session); + } + } + + protected String getInterpretedQuery2(Session session, Class type, File file) throws + Exception { + return getInterpretedQuery2(session, type, file, false); + } + + protected String getInterpretedQuery2(Session session, Class type, File file, + boolean interpretCount) throws Exception { + + QueryType queryType = PrismTestUtil.parseAtomicValue(file, QueryType.COMPLEX_TYPE); - LOGGER.info("QUERY TYPE TO CONVERT :\n{}", (query.getFilter() != null ? query.getFilter().debugDump(3) : null)); + LOGGER.info("QUERY TYPE TO CONVERT : {}", ObjectQueryUtil.dump(queryType)); + + ObjectQuery query = null; + try { + query = QueryJaxbConvertor.createObjectQuery((Class) type, queryType, prismContext); // TODO + } catch (Exception ex) { + LOGGER.info("error while converting query: " + ex.getMessage(), ex); + } + + return getInterpretedQuery2(session, type, query, interpretCount); + } + + protected String getInterpretedQuery2(Session session, Class type, ObjectQuery query) throws Exception { + return getInterpretedQuery2(session, type, query, false); + } + + + protected String getInterpretedQuery2(Session session, Class type, ObjectQuery query, + boolean interpretCount) throws Exception { + + if (query != null) { + LOGGER.info("QUERY TYPE TO CONVERT :\n{}", (query.getFilter() != null ? query.getFilter().debugDump(3) : null)); + } QueryEngine2 engine = new QueryEngine2(repositoryService.getConfiguration(), prismContext); RQuery rQuery = engine.interpret(query, type, null, interpretCount, session); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 553025f817b..c5469a00a3f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -16,58 +16,10 @@ package com.evolveum.midpoint.repo.sql; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.Visitable; -import com.evolveum.midpoint.prism.Visitor; - -import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; -import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; -import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.hibernate.Criteria; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.Query; -import org.hibernate.SQLQuery; -import org.hibernate.ScrollMode; -import org.hibernate.ScrollableResults; -import org.hibernate.Session; -import org.hibernate.criterion.Order; -import org.hibernate.criterion.Restrictions; -import org.hibernate.exception.ConstraintViolationException; -import org.hibernate.internal.SessionFactoryImpl; -import org.hibernate.jdbc.Work; -import org.hibernate.transform.Transformers; -import org.springframework.stereotype.Repository; - import com.evolveum.midpoint.common.InternalsConfig; import com.evolveum.midpoint.common.crypto.CryptoUtil; import com.evolveum.midpoint.prism.ConsistencyCheckScope; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -80,6 +32,8 @@ import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; @@ -87,6 +41,7 @@ import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.parser.XNodeProcessorEvaluationMode; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.polystring.PrismDefaultPolyStringNormalizer; import com.evolveum.midpoint.prism.query.AllFilter; @@ -96,16 +51,19 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RLookupTable; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.data.common.any.RValueType; +import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.query.QueryEngine; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.RQuery; +import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; @@ -133,13 +91,52 @@ import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.hibernate.Criteria; +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.Query; +import org.hibernate.SQLQuery; +import org.hibernate.ScrollMode; +import org.hibernate.ScrollableResults; +import org.hibernate.Session; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Restrictions; +import org.hibernate.exception.ConstraintViolationException; +import org.hibernate.internal.SessionFactoryImpl; +import org.hibernate.jdbc.Work; +import org.hibernate.transform.Transformers; +import org.springframework.stereotype.Repository; + +import javax.annotation.PostConstruct; +import javax.xml.namespace.QName; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; /** @@ -1045,7 +1042,6 @@ public SearchResultList> searchObjects(Cla if (filter instanceof NoneFilter) { subResult.recordSuccess(); return new SearchResultList(new ArrayList>(0)); - //shouldn't be this in ObjectQueryUtil.simplify? } else if (filter instanceof AllFilter){ query = query.cloneEmpty(); query.setFilter(null); @@ -1094,7 +1090,6 @@ public SearchResultList searchContainers(Class t if (filter instanceof NoneFilter) { result.recordSuccess(); return new SearchResultList(new ArrayList(0)); - //shouldn't be this in ObjectQueryUtil.simplify? } else if (filter instanceof AllFilter) { query = query.cloneEmpty(); query.setFilter(null); @@ -1181,33 +1176,39 @@ private SearchResultList> searchObjectsAtt return new SearchResultList>(list); } - private SearchResultList searchContainersAttempt(Class type, ObjectQuery query, + private SearchResultList searchContainersAttempt(Class type, ObjectQuery query, Collection> options, OperationResult result) throws SchemaException { + + if (!(AccessCertificationCaseType.class.equals(type))) { + throw new UnsupportedOperationException("Only AccessCertificationCaseType is supported here now."); + } + LOGGER_PERFORMANCE.debug("> search containers {}", new Object[]{type.getSimpleName()}); - List list = new ArrayList<>(); + List list = new ArrayList<>(); Session session = null; try { session = beginReadOnlyTransaction(); -// RQuery rQuery = engine.interpret(query, type, options, false, session); -// -// List objects = rQuery.list(); -// LOGGER.trace("Found {} objects, translating to JAXB.", new Object[]{(objects != null ? objects.size() : 0)}); -// -// for (GetObjectResult object : objects) { -// PrismObject prismObject = updateLoadedObject(object, type, options, session); -// list.add(prismObject); -// } + QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); + RQuery rQuery = engine.interpret(query, type, options, false, session); + + List items = rQuery.list(); + LOGGER.trace("Found {} items, translating to JAXB.", items.size()); + + for (GetObjectResult item : items) { + PrismContainerValue cvalue = (PrismContainerValue) updateLoadedCertificationCase(item, options, session); + list.add(cvalue.asContainerable()); + } session.getTransaction().commit(); - } catch (/*QueryException | */RuntimeException ex) { + } catch (QueryException | RuntimeException ex) { handleGeneralException(ex, session, result); } finally { cleanupSessionAndResult(session, result); } - return new SearchResultList(list); + return new SearchResultList(list); } /** @@ -1317,7 +1318,19 @@ public void visit(Visitable visitable) { return prismObject; } - + + + private PrismContainerValue updateLoadedCertificationCase(GetObjectResult result, + Collection> options, + Session session) throws SchemaException { + + AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), getPrismContext()); + PrismContainerValue cvalue = aCase.asPrismContainerValue(); + validateContainerValue(cvalue, AccessCertificationCaseType.class); + return cvalue; + } + + private Map consolidateResults(List> results){ Map oidNameMap = new HashMap(); for (Map map : results){ @@ -1872,6 +1885,18 @@ private void validateObjectType(PrismObject prismObjec } } + private void validateContainerValue(PrismContainerValue cvalue, Class type) + throws SchemaException { + if (cvalue == null) { + throw new SchemaException("Null object as a result of repository get operation for " + type); + } + Class realType = cvalue.asContainerable().getClass(); + if (!type.isAssignableFrom(realType)) { + throw new SchemaException("Expected to find '" + type.getSimpleName() + "' but found '" + realType.getSimpleName()); + } + // TODO call check consistence if possible + } + private RObject createDataObjectFromJAXB(PrismObject prismObject, PrismIdentifierGenerator.Operation operation) throws SchemaException { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index e8929598297..44847bf55df 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -265,6 +265,11 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 } public AccessCertificationCaseType toJAXB(PrismContext prismContext) throws SchemaException { + return createJaxb(fullObject, prismContext); + } + + // TODO find appropriate name + public static AccessCertificationCaseType createJaxb(byte[] fullObject, PrismContext prismContext) throws SchemaException { String xml = RUtil.getXmlFromByteArray(fullObject, false); PrismContainer caseContainer; try { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index 50cdc135d49..ee696ab7ebd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; @@ -57,7 +58,7 @@ public class InterpretationContext { private InterpreterHelper helper = new InterpreterHelper(this); - private Class type; + private Class type; private RootHibernateQuery hibernateQuery; @@ -68,7 +69,7 @@ public class InterpretationContext { */ private EntityDefinition rootEntityDefinition; - public InterpretationContext(QueryInterpreter2 interpreter, Class type, + public InterpretationContext(QueryInterpreter2 interpreter, Class type, PrismContext prismContext, Session session) throws QueryException { Validate.notNull(interpreter, "interpreter"); @@ -104,7 +105,7 @@ public QueryInterpreter2 getInterpreter() { return interpreter; } - public Class getType() { + public Class getType() { return type; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java index 5e34ddefa73..66042ac23a2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -16,9 +16,12 @@ package com.evolveum.midpoint.repo.sql.query2; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.ClassDefinitionParser; import com.evolveum.midpoint.repo.sql.query2.definition.Definition; import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; @@ -28,6 +31,7 @@ import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; @@ -73,6 +77,11 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { definitionsByClass.put(definition.getJpaType(), definition); } + // TODO fix this hack + EntityDefinition caseDefinition = classDefinitionParser.parseObjectTypeClass(AccessCertificationCaseType.COMPLEX_TYPE, + AccessCertificationCaseType.class, RAccessCertificationCase.class); + map.put(AccessCertificationCaseType.COMPLEX_TYPE, caseDefinition); + // link parents (maybe not needed at all, we'll see) for (EntityDefinition definition : map.values()) { Class superclass = definition.getJpaType().getSuperclass(); @@ -131,12 +140,22 @@ public EntityDefinition findEntityDefinition(QName typeName) { } // always returns non-null value - public EntityDefinition findEntityDefinition(Class type) { + public EntityDefinition findEntityDefinition(Class type) throws QueryException { Validate.notNull(type, "Type must not be null."); - return findEntityDefinition(ObjectTypes.getObjectType(type).getTypeQName()); + return findEntityDefinition(getQNameForType(type)); + } + + public QName getQNameForType(Class type) throws QueryException { + if (ObjectType.class.isAssignableFrom(type)) { + return ObjectTypes.getObjectType((Class) type).getTypeQName(); + } + if (AccessCertificationCaseType.class.equals(type)) { // TODO generalize + return AccessCertificationCaseType.COMPLEX_TYPE; + } + throw new QueryException("Unsupported type " + type); } - public DefinitionSearchResult findDefinition(Class type, ItemPath path, Class definitionType) { + public DefinitionSearchResult findDefinition(Class type, ItemPath path, Class definitionType) throws QueryException { Validate.notNull(type, "Type must not be null."); Validate.notNull(definitionType, "Definition type must not be null."); EntityDefinition entityDef = findEntityDefinition(type); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java index f98160105b2..f06867f28f4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryEngine2.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; @@ -47,7 +48,7 @@ public QueryEngine2(SqlRepositoryConfiguration config, PrismContext prismContext this.prismContext = prismContext; } - public RQuery interpret(ObjectQuery query, Class type, + public RQuery interpret(ObjectQuery query, Class type, Collection> options, boolean countingObjects, Session session) throws QueryException { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 48ad62a817b..d328ba701be 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; @@ -131,7 +132,7 @@ public SqlRepositoryConfiguration getRepoConfiguration() { return repoConfiguration; } - public RootHibernateQuery interpret(ObjectQuery query, Class type, + public RootHibernateQuery interpret(ObjectQuery query, Class type, Collection> options, PrismContext prismContext, boolean countingObjects, Session session) throws QueryException { Validate.notNull(type, "Type must not be null."); @@ -270,7 +271,7 @@ private ItemPath getFullPath(Restriction parent, ItemPath fullPath) { } } - private void interpretPagingAndSorting(InterpretationContext context, ObjectQuery query, boolean countingObjects) { + private void interpretPagingAndSorting(InterpretationContext context, ObjectQuery query, boolean countingObjects) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String rootAlias = hibernateQuery.getPrimaryEntityAlias(); @@ -302,7 +303,7 @@ protected void updatePagingAndSortingByOid(RootHibernateQuery hibernateQuery, Ob } } - public void updatePagingAndSorting(RootHibernateQuery hibernateQuery, Class type, ObjectPaging paging) { + public void updatePagingAndSorting(RootHibernateQuery hibernateQuery, Class type, ObjectPaging paging) throws QueryException { if (paging == null) { return; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index a2afcf026aa..aac26862e93 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -57,10 +57,12 @@ public EntityDefinition parseObjectTypeClass(Class type) ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(type); QName jaxbName = objectType.getQName(); Class jaxbType = objectType.getClassDefinition(); + return parseObjectTypeClass(jaxbName, jaxbType, type); + } - EntityDefinition entityDefinition = new EntityDefinition(jaxbName, jaxbType, type.getSimpleName(), type, null); + public EntityDefinition parseObjectTypeClass(QName jaxbName, Class jaxbType, Class jpaType) { + EntityDefinition entityDefinition = new EntityDefinition(jaxbName, jaxbType, jpaType.getSimpleName(), jpaType, null); updateEntityDefinition(entityDefinition); - return entityDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java index 149b372b05f..86f3df1f395 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java @@ -91,7 +91,7 @@ protected void debugDumpExtended(StringBuilder builder, int indent) { builder.append(definition.debugDump(indent+1)); builder.append('\n'); } - DebugUtil.indentDebugDump(builder, indent); // before final '}' + DebugUtil.indentDebugDump(builder, indent); // indentation before final '}' } @Override From 393fe6b8b43153d6e81d576fb8098a4258a62c6d Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 26 Nov 2015 00:25:57 +0100 Subject: [PATCH 017/116] Adapting Certification Manager to new repo implementation. Still missing intra-case updates, sorting and "no response" filters. --- .../dto/CertDecisionDtoProvider.java | 4 +- .../midpoint/prism/query/InOidFilter.java | 45 +-- .../midpoint/prism/query/ObjectPaging.java | 13 +- .../xml/ns/public/common/common-3.xsd | 2 +- .../api/CertificationManager.java | 18 +- .../impl/AccCertEventHelper.java | 18 +- .../impl/AccCertQueryHelper.java | 319 ++++++------------ .../impl/AccCertUpdateHelper.java | 24 +- ...onCloseStageApproachingTriggerHandler.java | 15 +- ...ssCertificationRemediationTaskHandler.java | 2 +- .../impl/CertificationManagerImpl.java | 8 +- .../test/AbstractCertificationTest.java | 10 +- .../test/BasicCertificationTest.java | 8 +- .../test/RoleInducementCertificationTest.java | 6 +- .../impl/helpers/CertHelper.java | 7 +- .../repo/sql/QueryInterpreter2Test.java | 216 +++++++++++- .../repo/sql/SqlRepositoryServiceImpl.java | 134 ++++++-- .../common/RAccessCertificationCampaign.java | 6 +- .../container/RAccessCertificationCase.java | 117 +++++-- .../sql/query2/InterpretationContext.java | 4 + .../repo/sql/query2/QueryInterpreter2.java | 14 +- .../query2/restriction/InOidRestriction.java | 33 +- .../restriction/ItemValueRestriction.java | 16 +- .../repo/sql/util/GetObjectResult.java | 9 +- 24 files changed, 641 insertions(+), 407 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertDecisionDtoProvider.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertDecisionDtoProvider.java index 456f9bf0ec0..0852a921a3f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertDecisionDtoProvider.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertDecisionDtoProvider.java @@ -78,7 +78,7 @@ public Iterator internalIterator(long first, long count) { SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); CertificationManager certificationManager = getPage().getCertificationManager(); - List caseList = certificationManager.searchDecisions(campaignQuery, caseQuery, reviewerOid, notDecidedOnly, resolveNames, task, result); + List caseList = certificationManager.searchDecisions(caseQuery, reviewerOid, notDecidedOnly, resolveNames, task, result); for (AccessCertificationCaseType _case : caseList) { getAvailableData().add(new CertDecisionDto(_case, getPage())); @@ -114,7 +114,7 @@ protected int internalSize() { CertificationManager certificationManager = getPage().getCertificationManager(); ObjectQuery query = getQuery().clone(); query.setPaging(null); // when counting decisions we need to exclude offset+size (and sorting info is irrelevant) - List caseList = certificationManager.searchDecisions(campaignQuery, query, reviewerOid, notDecidedOnly, null, task, result); + List caseList = certificationManager.searchDecisions(query, reviewerOid, notDecidedOnly, null, task, result); count = caseList.size(); } catch (Exception ex) { result.recordFatalError("Couldn't count objects.", ex); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java index f568129bc45..06a242bf3f2 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java @@ -20,16 +20,10 @@ import java.util.Collection; import java.util.Iterator; -import javax.xml.namespace.QName; - import org.apache.commons.lang.StringUtils; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -37,8 +31,10 @@ public class InOidFilter extends ObjectFilter { private Collection oids; private ExpressionWrapper expression; + private boolean considerOwner; // temporary hack (checks owner OID) - InOidFilter(Collection oids) { + InOidFilter(boolean considerOwner, Collection oids) { + this.considerOwner = considerOwner; this.oids = oids; } @@ -47,13 +43,21 @@ public class InOidFilter extends ObjectFilter { } public static InOidFilter createInOid(Collection oids){ - return new InOidFilter(oids); + return new InOidFilter(false, oids); } public static InOidFilter createInOid(String... oids){ - return new InOidFilter(Arrays.asList(oids)); + return new InOidFilter(false, Arrays.asList(oids)); } - + + public static InOidFilter createOwnerHasOidIn(Collection oids){ + return new InOidFilter(true, oids); + } + + public static InOidFilter createOwnerHasOidIn(String... oids){ + return new InOidFilter(true, Arrays.asList(oids)); + } + public static InOidFilter createInOid(ExpressionWrapper expression){ return new InOidFilter(expression); } @@ -65,7 +69,11 @@ public Collection getOids() { public void setOids(Collection oids) { this.oids = oids; } - + + public boolean isConsiderOwner() { + return considerOwner; + } + public ExpressionWrapper getExpression() { return expression; } @@ -74,8 +82,6 @@ public void setExpression(ExpressionWrapper expression) { this.expression = expression; } - - @Override public void checkConsistence() { if (oids == null) { @@ -97,22 +103,21 @@ public String debugDump() { public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); sb.append("IN OID: "); - - - sb.append("\n"); - DebugUtil.indentDebugDump(sb, indent+1); + if (considerOwner) { + sb.append("(for owner)"); + } sb.append("VALUE:"); if (getOids() != null) { sb.append("\n"); for (String oid : getOids()) { + DebugUtil.indentDebugDump(sb, indent+1); sb.append(oid); sb.append("\n"); } } else { - sb.append(" null"); + sb.append(" null\n"); } - return sb.toString(); } @@ -139,7 +144,7 @@ public String toString() { @Override public InOidFilter clone() { - InOidFilter inOid = new InOidFilter(getOids()); + InOidFilter inOid = new InOidFilter(considerOwner, getOids()); inOid.setExpression(getExpression()); return inOid; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java index f52e6480e89..14f08d24bc5 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java @@ -36,12 +36,17 @@ protected ObjectPaging() { // TODO Auto-generated constructor stub } - ObjectPaging(Integer offset, Integer maxSize){ + ObjectPaging(Integer offset, Integer maxSize) { this.offset = offset; this.maxSize = maxSize; } - ObjectPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction){ + public ObjectPaging(ItemPath orderBy, OrderDirection direction) { + this.orderBy = orderBy; + this.direction = direction; + } + + ObjectPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction) { this.offset = offset; this.maxSize = maxSize; this.orderBy = orderBy; @@ -63,6 +68,10 @@ public static ObjectPaging createPaging(Integer offset, Integer maxSize, ItemPat public static ObjectPaging createPaging(Integer offset, Integer maxSize, String orderBy, String namespace, OrderDirection direction){ return createPaging(offset, maxSize, new QName(namespace, orderBy), direction); } + + public static ObjectPaging createPaging(ItemPath orderBy, OrderDirection direction) { + return new ObjectPaging(orderBy, direction); + } public static ObjectPaging createEmptyPaging(){ return new ObjectPaging(); diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 66b9af61885..57926b57aa6 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -12733,7 +12733,7 @@ --> - + Is the case enabled for the current stage? E.g. cases that have been marked as "remove" in a given stage diff --git a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java index b910d89e26c..82866f0dc66 100644 --- a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java +++ b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java @@ -87,8 +87,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * depending on the certification definition (scope and handler). In all stages, reviewers will be assigned * to cases, based again on the definition (reviewer specification in stage definition and handler). * - * @param campaign Certification campaign. If its definition reference is already resolved, it will be used. - * Otherwise, the implementation will resolve the definition by itself. + * @param campaignOid Certification campaign OID. * @param stageNumber Stage that has to be open. This has to be the stage after the current one (or the first one). * @param task Task in context of which all operations will take place. * @param parentResult Result for the operations. @@ -102,8 +101,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * depending on the certification definition (scope and handler). In all stages, reviewers will be assigned * to cases, based again on the definition (reviewer specification in stage definition and handler). * - * @param campaign Certification campaign. If its definition reference is already resolved, it will be used. - * Otherwise, the implementation will resolve the definition by itself. + * @param campaignOid Certification campaign OID. * @param stageNumber Stage that has to be closed. This has to be the current stage. * @param task Task in context of which all operations will take place. * @param parentResult Result for the operations. @@ -114,7 +112,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * Starts the remediation phase for the campaign. * The campaign has to be in the last stage and that stage has to be already closed. * - * @param campaign + * @param campaignOid * @param task * @param result */ @@ -123,7 +121,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType /** * Closes a campaign. * - * @param campaign + * @param campaignOid * @param task * @param result */ @@ -140,7 +138,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * - name of object, by setting paging.orderBy = objectRef * - name of target, by setting paging.orderBy = targetRef * Note that in order to use names as a sorting criteria, it is necessary to include RESOLVE_NAMES option in the operation call. - * Paging is specified by offset (counting from 0) and maxSize. Paging cooke is ignored. + * Paging is specified by offset (counting from 0) and maxSize. Paging cookie is ignored. * * NOTE THAT THE SORTING INTERFACE WILL PROBABLY BE CHANGED IN NEAR FUTURE. * @@ -175,8 +173,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * - name of campaign, by setting paging.orderBy = campaignRef * - deadline or reviewRequestedTimestamp, by setting paging.orderBy = reviewDeadline/reviewRequestedTimestamp * - * @param campaignQuery Specification of campaigns to query. - * @param caseQuery Specification of the cases to retrieve. + * @param caseQuery Specification of the cases to retrieve. (In future it may contain restrictions on owning campaign(s).) * @param reviewerOid OID of the reviewer whose decisions we want to retrieve. * @param notDecidedOnly If true, only response==(NO_DECISION or null) should be returned. * It is currently not possible to formulate this using Query API @@ -185,9 +182,10 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * @param task Task in context of which all operations will take place. * @param parentResult Result for the operations. * @return A list of relevant certification cases. + * */ - List searchDecisions(ObjectQuery campaignQuery, ObjectQuery caseQuery, + List searchDecisions(ObjectQuery caseQuery, String reviewerOid, boolean notDecidedOnly, Collection> options, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException; diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java index d8f57807d04..bff0eb39852 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java @@ -95,9 +95,9 @@ public void onReviewDeadlineApproaching(ObjectReferenceType reviewerRef, List getCurrentReviewers(AccessCertificationCampaignType campaign) { + public Collection getCurrentReviewers(List caseList) { Set oids = new HashSet<>(); - for (AccessCertificationCaseType aCase : campaign.getCase()) { + for (AccessCertificationCaseType aCase : caseList) { if (Boolean.TRUE.equals(aCase.isEnabled())) { for (ObjectReferenceType reviewerRef : aCase.getReviewerRef()) { oids.add(reviewerRef.getOid()); @@ -107,18 +107,4 @@ public Collection getCurrentReviewers(AccessCertificationCampaignType ca return oids; } - public List getCasesForReviewer(AccessCertificationCampaignType campaign, String oid) { - List rv = new ArrayList<>(); - for (AccessCertificationCaseType aCase : campaign.getCase()) { - if (Boolean.TRUE.equals(aCase.isEnabled())) { - for (ObjectReferenceType reviewerRef : aCase.getReviewerRef()) { - if (oid.equals(reviewerRef.getOid())) { - rv.add(aCase.clone()); - break; - } - } - } - } - return rv; - } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java index 5aab0fd1ad4..0ba0fc66223 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java @@ -18,17 +18,9 @@ import com.evolveum.midpoint.model.api.ModelService; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; -import com.evolveum.midpoint.prism.parser.XNodeSerializer; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.query.RefFilter; +import com.evolveum.midpoint.prism.query.*; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; @@ -36,7 +28,6 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; @@ -44,7 +35,6 @@ import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; @@ -54,14 +44,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; +import java.util.*; /** * @author mederly @@ -89,65 +72,80 @@ public class AccCertQueryHelper { protected RepositoryService repositoryService; protected List searchCases(String campaignOid, ObjectQuery query, Collection> options, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException { - ObjectFilter filter = query != null ? query.getFilter() : null; - ObjectPaging paging = query != null ? query.getPaging() : null; - AccessCertificationCampaignType campaign = helper.getCampaign(campaignOid, options, task, result); - List caseList = getCases(campaign, filter, task, result); - caseList = doSortingAndPaging(caseList, paging); + ObjectQuery newQuery; + InOidFilter inOidFilter = InOidFilter.createOwnerHasOidIn(campaignOid); + if (query == null) { + newQuery = ObjectQuery.createObjectQuery(inOidFilter); + } else { + newQuery = query.clone(); + if (query.getFilter() == null) { + newQuery.setFilter(inOidFilter); + } else { + newQuery.setFilter(AndFilter.createAnd(query.getFilter(), inOidFilter)); + } + } + List caseList = repositoryService.searchContainers(AccessCertificationCaseType.class, newQuery, options, result); return caseList; } - protected List searchDecisions(ObjectQuery campaignQuery, ObjectQuery caseQuery, String reviewerOid, boolean notDecidedOnly, Collection> options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException { - // enhance filter with reviewerRef - ObjectFilter enhancedFilter; + protected List searchDecisions(ObjectQuery query, String reviewerOid, boolean notDecidedOnly, Collection> options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException { + + // enhance filter with reviewerRef + enabled + ObjectQuery newQuery; ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); ObjectFilter enabledFilter = EqualFilter.createEqual( AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); - ObjectFilter andFilter = AndFilter.createAnd(reviewerFilter, enabledFilter); - - if (caseQuery == null || caseQuery.getFilter() == null) { - enhancedFilter = andFilter; + ObjectFilter reviewerAndEnabledFilter = AndFilter.createAnd(reviewerFilter, enabledFilter); + if (query == null) { + newQuery = ObjectQuery.createObjectQuery(reviewerAndEnabledFilter); } else { - enhancedFilter = AndFilter.createAnd(caseQuery.getFilter(), andFilter); + newQuery = query.clone(); + if (query.getFilter() == null) { + newQuery.setFilter(reviewerAndEnabledFilter); + } else { + newQuery.setFilter(AndFilter.createAnd(query.getFilter(), reviewerAndEnabledFilter)); + } } // retrieve cases, filtered - List> campaignObjects = modelService.searchObjects(AccessCertificationCampaignType.class, campaignQuery, options, task, result); - List caseList = new ArrayList<>(); - for (PrismObject campaignObject : campaignObjects) { - AccessCertificationCampaignType campaign = campaignObject.asObjectable(); - if (!AccessCertificationCampaignStateType.IN_REVIEW_STAGE.equals(campaign.getState())) { + List caseList = repositoryService.searchContainers(AccessCertificationCaseType.class, newQuery, options, result); + + // campaigns already loaded + Map campaigns = new HashMap<>(); + + // remove irrelevant decisions from each case and add campaignRef + for (AccessCertificationCaseType _case : caseList) { + if (_case.getCampaignRef() == null) { + LOGGER.warn("AccessCertificationCaseType {} has no campaignRef -- skipping it", _case); continue; } - List campaignCases = getCases(campaign, enhancedFilter, task, result); + // obtain campaign object + String campaignOid = _case.getCampaignRef().getOid(); + AccessCertificationCampaignType campaign = campaigns.get(campaignOid); + if (campaign == null) { + campaign = repositoryService.getObject(AccessCertificationCampaignType.class, campaignOid, null, result).asObjectable(); // TODO error checking + call model instead of repo + campaigns.put(campaignOid, campaign); + } - // remove irrelevant decisions from each case - // and add campaignRef int stage = campaign.getCurrentStageNumber(); - for (AccessCertificationCaseType _case : campaignCases) { - Iterator decisionIterator = _case.getDecision().iterator(); - while (decisionIterator.hasNext()) { - AccessCertificationDecisionType decision = decisionIterator.next(); - if (decision.getStageNumber() != stage || !decision.getReviewerRef().getOid().equals(reviewerOid)) { - decisionIterator.remove(); - } - } - - if (!notDecidedOnly || !isDecided(_case)) { - ObjectReferenceType campaignRef = ObjectTypeUtil.createObjectRef(campaignObject); - campaignRef.asReferenceValue().setObject(campaignObject); - _case.setCampaignRef(campaignRef); - caseList.add(_case); + Iterator decisionIterator = _case.getDecision().iterator(); + while (decisionIterator.hasNext()) { + AccessCertificationDecisionType decision = decisionIterator.next(); + if (decision.getStageNumber() != stage || !decision.getReviewerRef().getOid().equals(reviewerOid)) { + decisionIterator.remove(); } } - } - // sort and page cases - ObjectPaging paging = caseQuery != null ? caseQuery.getPaging() : null; - caseList = doSortingAndPaging(caseList, paging); +// if (!notDecidedOnly || !isDecided(_case)) { +// ObjectReferenceType campaignRef = ObjectTypeUtil.createObjectRef(campaignObject); +// campaignRef.asReferenceValue().setObject(campaignObject); +// _case.setCampaignRef(campaignRef); +// caseList.add(_case); +// } + } return caseList; } @@ -164,182 +162,55 @@ private boolean isDecided(AccessCertificationCaseType _case) { return response != null && response != AccessCertificationResponseType.NO_RESPONSE; } - - protected List doSortingAndPaging(List caseList, ObjectPaging paging) { - if (paging == null) { - return caseList; - } - - // sorting - if (paging.getOrderBy() != null) { - Comparator comparator = createComparator(paging.getOrderBy(), paging.getDirection()); - if (comparator != null) { - caseList = new ArrayList<>(caseList); - Collections.sort(caseList, comparator); - } - } - // paging - if (paging.getOffset() != null || paging.getMaxSize() != null) { - int offset = paging.getOffset() != null ? paging.getOffset() : 0; - int maxSize = paging.getMaxSize() != null ? paging.getMaxSize() : Integer.MAX_VALUE; - if (offset >= caseList.size()) { - caseList = new ArrayList<>(); - } else { - if (maxSize > caseList.size() - offset) { - maxSize = caseList.size() - offset; - } - caseList = caseList.subList(offset, offset+maxSize); - } - } + public List getCasesForReviewer(AccessCertificationCampaignType campaign, + String reviewerOid, Task task, OperationResult result) + throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException { + ObjectFilter filter = AndFilter.createAnd( + RefFilter.createReferenceEqual( + new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), + AccessCertificationCaseType.class, + prismContext, + ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER).asReferenceValue()), + EqualFilter.createEqual( + new ItemPath(AccessCertificationCaseType.F_ENABLED), + AccessCertificationCaseType.class, + prismContext, + true) + ); + + List caseList = searchCases(campaign.getOid(), ObjectQuery.createObjectQuery(filter), null, task, result); return caseList; } - protected List getCases(AccessCertificationCampaignType campaign, ObjectFilter filter, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException { - // temporary implementation: simply fetches the whole campaign and selects requested items by itself - List caseList = campaign.getCase(); + public AccessCertificationCaseType getCase(String campaignOid, long caseId, OperationResult result) throws SchemaException { + ObjectFilter filter = AndFilter.createAnd( + InOidFilter.createOwnerHasOidIn(campaignOid), + InOidFilter.createInOid(String.valueOf(caseId)) + ); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); - // filter items - if (filter != null) { - Iterator caseIterator = caseList.iterator(); - while (caseIterator.hasNext()) { - AccessCertificationCaseType _case = caseIterator.next(); - if (!ObjectQuery.match(_case, filter, matchingRuleRegistry)) { - caseIterator.remove(); - } - } - } - - return caseList; - } - - /** - * Experimental implementation: we support ordering by object object name, target object name. - * However, there are no QNames that exactly match these options. So we map the following QNames to ordering attributes: - * - * F_OBJECT_REF -> ordering by object name - * F_TARGET_REF -> ordering by target name - * - * The requirement is that object names were fetched as well (resolveNames option) - * - */ - private Comparator createComparator(ItemPath orderBy, OrderDirection direction) { - if (new ItemPath(AccessCertificationCaseType.F_OBJECT_REF).equivalent(orderBy)) { - return createObjectNameComparator(direction); - } else if (new ItemPath(AccessCertificationCaseType.F_TARGET_REF).equivalent(orderBy)) { - return createTargetNameComparator(direction); - } else if (new ItemPath(AccessCertificationCaseType.F_CAMPAIGN_REF).equivalent(orderBy)) { - return createCampaignNameComparator(direction); - } else if (new ItemPath(AccessCertificationCaseType.F_REVIEW_REQUESTED_TIMESTAMP).equivalent(orderBy)) { - return createReviewRequestedComparator(direction); - } else if (new ItemPath(AccessCertificationCaseType.F_REVIEW_DEADLINE).equivalent(orderBy)) { - return createReviewDeadlineComparator(direction); - } else { - LOGGER.warn("Unsupported sorting attribute {}. Results will not be sorted.", orderBy); + List caseList = repositoryService.searchContainers(AccessCertificationCaseType.class, query, null, result); + if (caseList.isEmpty()) { return null; + } else if (caseList.size() == 1) { + return caseList.get(0); + } else { + throw new IllegalStateException("More than one certification case with ID " + caseId + " in campaign " + campaignOid); } } - private Comparator createObjectNameComparator(final OrderDirection direction) { - return new Comparator() { - @Override - public int compare(AccessCertificationCaseType o1, AccessCertificationCaseType o2) { - return compareRefNames(o1.getObjectRef(), o2.getObjectRef(), direction); - } - }; - } - - private Comparator createTargetNameComparator(final OrderDirection direction) { - return new Comparator() { - @Override - public int compare(AccessCertificationCaseType o1, AccessCertificationCaseType o2) { - return compareRefNames(o1.getTargetRef(), o2.getTargetRef(), direction); - } - }; - } - - private Comparator createCampaignNameComparator(final OrderDirection direction) { - return new Comparator() { - @Override - public int compare(AccessCertificationCaseType o1, AccessCertificationCaseType o2) { - AccessCertificationCampaignType c1 = getCampaign(o1); - AccessCertificationCampaignType c2 = getCampaign(o2); - if (c1 == null) { - return respectDirection(-1, direction); - } else if (c2 == null) { - return respectDirection(1, direction); + public List selectCasesForReviewer(List caseList, String reviewerOid) { + List rv = new ArrayList<>(); + for (AccessCertificationCaseType aCase : caseList) { + if (Boolean.TRUE.equals(aCase.isEnabled())) { + for (ObjectReferenceType reviewerRef : aCase.getReviewerRef()) { + if (reviewerOid.equals(reviewerRef.getOid())) { + rv.add(aCase.clone()); + break; + } } - int ordering = c1.getName().getNorm().compareTo(c2.getName().getNorm()); - //int ordering = c1.getName().getOrig().compareTo(c2.getName().getOrig()); - return respectDirection(ordering, direction); } - }; - } - - private Comparator createReviewRequestedComparator(final OrderDirection direction) { - return new Comparator() { - @Override - public int compare(AccessCertificationCaseType o1, AccessCertificationCaseType o2) { - return compareDates(o1.getReviewRequestedTimestamp(), o2.getReviewRequestedTimestamp(), direction); - } - }; - } - - private Comparator createReviewDeadlineComparator(final OrderDirection direction) { - return new Comparator() { - @Override - public int compare(AccessCertificationCaseType o1, AccessCertificationCaseType o2) { - return compareDates(o1.getReviewDeadline(), o2.getReviewDeadline(), direction); - } - }; - } - - private int compareDates(XMLGregorianCalendar d1, XMLGregorianCalendar d2, OrderDirection direction) { - if (d1 == null) { - return respectDirection(1, direction); // null is later - } else if (d2 == null) { - return respectDirection(-1, direction); - } else { - return respectDirection(d1.compare(d2), direction); } + return rv; } - - - private AccessCertificationCampaignType getCampaign(AccessCertificationCaseType c) { - if (c == null || c.getCampaignRef() == null || c.getCampaignRef().asReferenceValue().getObject() == null) { - return null; - } - return (AccessCertificationCampaignType) c.getCampaignRef().asReferenceValue().getObject().asObjectable(); - } - - - private int compareRefNames(ObjectReferenceType leftRef, ObjectReferenceType rightRef, OrderDirection direction) { - if (leftRef == null) { - return respectDirection(1, direction); // null > anything - } else if (rightRef == null) { - return respectDirection(-1, direction); // anything < null - } - - // brutal hack - we (mis)use the fact that names are serialized as XNode comments -// String leftName = (String) leftRef.asReferenceValue().getUserData(XNodeSerializer.USER_DATA_KEY_COMMENT); -// String rightName = (String) rightRef.asReferenceValue().getUserData(XNodeSerializer.USER_DATA_KEY_COMMENT); - String leftName = leftRef.asReferenceValue().getTargetName() != null ? leftRef.asReferenceValue().getTargetName().getOrig() : null; - String rightName = rightRef.asReferenceValue().getTargetName() != null ? rightRef.asReferenceValue().getTargetName().getOrig() : null; - if (leftName == null) { - return respectDirection(1, direction); // null > anything - } else if (rightName == null) { - return respectDirection(-1, direction); // anything < null - } - - int ordering = leftName.toUpperCase().compareTo(rightName.toUpperCase()); // brutal hack (we need to compare on normalized values) - return respectDirection(ordering, direction); - } - - private int respectDirection(int ordering, OrderDirection direction) { - if (direction == OrderDirection.ASCENDING) { - return ordering; - } else { - return -ordering; - } - } - } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java index 40822b9655a..5fcf7da54ff 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java @@ -159,7 +159,7 @@ void recordDecision(AccessCertificationCampaignType campaign, long caseId, Acces decision.setReviewerRef(ObjectTypeUtil.createObjectRef(currentUser)); } - AccessCertificationCaseType _case = CertCampaignTypeUtil.findCase(campaign, caseId); + AccessCertificationCaseType _case = queryHelper.getCase(campaignOid, caseId, result); if (_case == null) { throw new ObjectNotFoundException("Case " + caseId + " was not found in campaign " + ObjectTypeUtil.toShortString(campaign)); } @@ -307,8 +307,9 @@ private void createCases(final AccessCertificationCampaignType campaign, AccessC } AccessCertificationObjectBasedScopeType objectBasedScope = (AccessCertificationObjectBasedScopeType) scope; - if (!campaign.getCase().isEmpty()) { - throw new IllegalStateException("Unexpected " + campaign.getCase().size() + " certification case(s) in campaign object " + campaignShortName + ". At this time there should be none."); + List existingCases = queryHelper.searchCases(campaign.getOid(), null, null, task, result); + if (!existingCases.isEmpty()) { + throw new IllegalStateException("Unexpected " + existingCases.size() + " certification case(s) in campaign object " + campaignShortName + ". At this time there should be none."); } // create a query to find target objects from which certification cases will be created @@ -395,7 +396,7 @@ public boolean handle(PrismObject object, OperationResult parentResu private void updateCases(AccessCertificationCampaignType campaign, AccessCertificationStageType stage, Task task, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException, SecurityViolationException, ConfigurationException, CommunicationException { LOGGER.trace("Updating reviewers and timestamps for cases in {}", ObjectTypeUtil.toShortString(campaign)); - List caseList = campaign.getCase(); + List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); int stageToBe = campaign.getCurrentStageNumber() + 1; @@ -477,8 +478,9 @@ private void updateCases(AccessCertificationCampaignType campaign, AccessCertifi } - void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCertificationStageType newStage, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { + void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCertificationStageType newStage, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SecurityViolationException, ConfigurationException, CommunicationException { // some bureaucracy... stage#, state, start time, trigger + List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); List itemDeltaList = new ArrayList<>(); PropertyDelta stageNumberDelta = createStageNumberDelta(newStage.getNumber()); itemDeltaList.add(stageNumberDelta); @@ -528,16 +530,16 @@ void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCerti eventHelper.onCampaignStart(campaign, task, result); } eventHelper.onCampaignStageStart(campaign, task, result); - Collection reviewers = eventHelper.getCurrentReviewers(campaign); + Collection reviewers = eventHelper.getCurrentReviewers(caseList); for (String reviewerOid : reviewers) { - List cases = eventHelper.getCasesForReviewer(campaign, reviewerOid); + List cases = queryHelper.getCasesForReviewer(campaign, reviewerOid, task, result); ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); eventHelper.onReviewRequested(reviewerRef, cases, campaign, task, result); } } - void recordCloseCurrentState(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { - List campaignDeltaList = createCurrentResponsesDeltas(campaign); + void recordCloseCurrentState(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SecurityViolationException, ConfigurationException, CommunicationException { + List campaignDeltaList = createCurrentResponsesDeltas(campaign, task, result); PropertyDelta stateDelta = createStateDelta(REVIEW_STAGE_DONE); campaignDeltaList.add(stateDelta); ContainerDelta triggerDelta = createTriggerDeleteDelta(); @@ -552,11 +554,11 @@ private ContainerDelta createTriggerDeleteDelta() { return ContainerDelta.createModificationReplace(ObjectType.F_TRIGGER, helper.getCampaignObjectDefinition()); } - private List createCurrentResponsesDeltas(AccessCertificationCampaignType campaign) { + private List createCurrentResponsesDeltas(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ConfigurationException, ObjectNotFoundException, SchemaException, CommunicationException, SecurityViolationException { List campaignDeltaList = new ArrayList<>(); LOGGER.trace("Updating current response for cases in {}", ObjectTypeUtil.toShortString(campaign)); - List caseList = campaign.getCase(); + List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); for (int i = 0; i < caseList.size(); i++) { AccessCertificationCaseType _case = caseList.get(i); diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java index d0449e46b5c..6bf872fd156 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java @@ -23,6 +23,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -54,7 +55,10 @@ public class AccessCertificationCloseStageApproachingTriggerHandler implements T @Autowired private AccCertEventHelper eventHelper; - + + @Autowired + private AccCertQueryHelper queryHelper; + @PostConstruct private void initialize() { triggerHandlerRegistry.register(HANDLER_URI, this); @@ -78,13 +82,14 @@ public void handle(PrismObject prismObject, Task task, } eventHelper.onCampaignStageDeadlineApproaching(campaign, task, result); - Collection reviewers = eventHelper.getCurrentReviewers(campaign); + List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); + Collection reviewers = eventHelper.getCurrentReviewers(caseList); for (String reviewerOid : reviewers) { - List caseList = eventHelper.getCasesForReviewer(campaign, reviewerOid); + List reviewerCaseList = queryHelper.selectCasesForReviewer(caseList, reviewerOid); ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); - eventHelper.onReviewDeadlineApproaching(reviewerRef, caseList, campaign, task, result); + eventHelper.onReviewDeadlineApproaching(reviewerRef, reviewerCaseList, campaign, task, result); } - } catch (RuntimeException e) { + } catch (SchemaException|SecurityViolationException|ObjectNotFoundException|CommunicationException|ConfigurationException|RuntimeException e) { LoggingUtils.logException(LOGGER, "Couldn't generate 'deadline approaching' notifications", e); } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationRemediationTaskHandler.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationRemediationTaskHandler.java index bb56c239531..c2572cfa3e3 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationRemediationTaskHandler.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationRemediationTaskHandler.java @@ -108,7 +108,7 @@ public TaskRunResult run(Task task) { int revokedOk = 0; int revokedError = 0; - List caseList = certificationManager.searchCases((String) campaignOid, (com.evolveum.midpoint.prism.query.ObjectQuery) null, (java.util.Collection>) null, (Task) task, (OperationResult) opResult); + List caseList = certificationManager.searchCases(campaignOid, (com.evolveum.midpoint.prism.query.ObjectQuery) null, (java.util.Collection>) null, (Task) task, (OperationResult) opResult); for (AccessCertificationCaseType _case : caseList) { if (helper.isRevoke(_case, campaign)) { OperationResult caseResult = opResult.createMinorSubresult(opResult.getOperation()+".revoke"); diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java index 00a9bd07483..4b693f93869 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java @@ -313,7 +313,7 @@ public List searchCases(String campaignOid, ObjectQ } @Override - public List searchDecisions(ObjectQuery campaignQuery, ObjectQuery caseQuery, + public List searchDecisions(ObjectQuery caseQuery, String reviewerOid, boolean notDecidedOnly, Collection> options, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, CommunicationException { @@ -325,7 +325,7 @@ public List searchDecisions(ObjectQuery campaignQue OperationResult result = parentResult.createSubresult(OPERATION_SEARCH_DECISIONS); try { - return queryHelper.searchDecisions(campaignQuery, caseQuery, reviewerOid, notDecidedOnly, options, task, result); + return queryHelper.searchDecisions(caseQuery, reviewerOid, notDecidedOnly, options, task, result); } catch (RuntimeException e) { result.recordFatalError("Couldn't search for certification decisions: unexpected exception: " + e.getMessage(), e); throw e; @@ -386,8 +386,10 @@ public AccessCertificationCasesStatisticsType getCampaignStatistics(String campa int currentStageNumber = campaign.getCurrentStageNumber(); AccessCertificationCampaignStateType state = campaign.getState(); + List campaignCases = queryHelper.searchCases(campaign.getOid(), null, null, task, result); + int accept=0, revoke=0, revokeRemedied=0, reduce=0, reduceRemedied=0, delegate=0, noDecision=0, noResponse=0; - for (AccessCertificationCaseType _case : campaign.getCase()) { + for (AccessCertificationCaseType _case : campaignCases) { if (currentStageOnly && !_case.isEnabled()) { continue; } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java index 8d7a8792d5b..1507c15318c 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java @@ -269,7 +269,7 @@ protected void assertDefinitionAndOwner(AccessCertificationCampaignType campaign protected void assertCaseReviewers(AccessCertificationCaseType _case, AccessCertificationResponseType currentResponse, boolean enabled, int currentResponseStage, List reviewerOidList) { assertEquals("wrong current response", currentResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", (Boolean) enabled, _case.isEnabled()); + assertEquals("wrong enabled", enabled, _case.isEnabled()); assertEquals("wrong current response stage number", (Integer) currentResponseStage, _case.getCurrentResponseStage()); Set realReviewerOids = new HashSet<>(); for (ObjectReferenceType ref : _case.getReviewerRef()) { @@ -302,19 +302,19 @@ protected void assertDecision(AccessCertificationCaseType _case, AccessCertifica assertEquals("wrong stage number", stageNumber, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", (Boolean) enabled, _case.isEnabled()); + assertEquals("wrong enabled", enabled, _case.isEnabled()); } protected void assertNoDecision(AccessCertificationCaseType _case, AccessCertificationResponseType aggregatedResponse, boolean enabled) { assertEquals("wrong # of decisions", 0, _case.getDecision().size()); assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", (Boolean) enabled, _case.isEnabled()); + assertEquals("wrong enabled", enabled, _case.isEnabled()); } protected void assertCurrentState(AccessCertificationCaseType _case, AccessCertificationResponseType aggregatedResponse, int currentResponseStage, boolean enabled) { assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); assertEquals("wrong current response stage number", (Integer) currentResponseStage, _case.getCurrentResponseStage()); - assertEquals("wrong enabled", (Boolean) enabled, _case.isEnabled()); + assertEquals("wrong enabled", enabled, _case.isEnabled()); } protected void assertDecisions(AccessCertificationCaseType _case, int count) { @@ -329,7 +329,7 @@ protected void assertDecision2(AccessCertificationCaseType _case, AccessCertific assertEquals("wrong comment", comment, decision.getComment()); assertApproximateTime("timestamp", new Date(), decision.getTimestamp()); assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", (Boolean) enabled, _case.isEnabled()); + assertEquals("wrong enabled", enabled, _case.isEnabled()); } } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java index e57bc00a814..d1783dd7b98 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java @@ -253,7 +253,7 @@ public void test050SearchDecisions() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); List caseList = - certificationManager.searchDecisions(null, null, USER_ADMINISTRATOR_OID, false, null, task, result); + certificationManager.searchDecisions(null, USER_ADMINISTRATOR_OID, false, null, task, result); // THEN TestUtil.displayThen(TEST_NAME); @@ -307,7 +307,7 @@ public void test100RecordDecision() throws Exception { assertEquals("wrong stage number", 1, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", AccessCertificationResponseType.ACCEPT, superuserCase.getCurrentResponse()); - assertEquals("wrong enabled", Boolean.TRUE, superuserCase.isEnabled()); + assertEquals("wrong enabled", true, superuserCase.isEnabled()); } @Test @@ -351,7 +351,7 @@ public void test105RecordAcceptJackCeo() throws Exception { assertEquals("wrong stage number", 1, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", AccessCertificationResponseType.ACCEPT, ceoCase.getCurrentResponse()); - assertEquals("wrong enabled", Boolean.TRUE, ceoCase.isEnabled()); + assertEquals("wrong enabled", true, ceoCase.isEnabled()); } @Test @@ -396,7 +396,7 @@ public void test110RecordRevokeJackCeo() throws Exception { assertEquals("wrong stage number", 1, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", AccessCertificationResponseType.REVOKE, ceoCase.getCurrentResponse()); - assertEquals("wrong enabled", Boolean.TRUE, ceoCase.isEnabled()); + assertEquals("wrong enabled", true, ceoCase.isEnabled()); } protected void checkAllCases(Collection caseList) { diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java index f1fbb26b679..80634fc333a 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java @@ -281,7 +281,7 @@ public void test050SearchDecisionsAdministrator() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); List caseList = - certificationManager.searchDecisions(null, null, USER_ADMINISTRATOR_OID, false, null, task, result); + certificationManager.searchDecisions(null, USER_ADMINISTRATOR_OID, false, null, task, result); /* Expected cases - phase 1: @@ -314,7 +314,7 @@ public void test051SearchDecisionsElaine() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); List caseList = - certificationManager.searchDecisions(null, null, USER_ELAINE_OID, false, null, task, result); + certificationManager.searchDecisions(null, USER_ELAINE_OID, false, null, task, result); /* Expected cases - phase 1: @@ -343,7 +343,7 @@ public void test052SearchDecisionsJack() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); List caseList = - certificationManager.searchDecisions(null, null, USER_JACK_OID, false, null, task, result); + certificationManager.searchDecisions(null, USER_JACK_OID, false, null, task, result); /* Expected cases - phase 1: NONE */ diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java index 963568b4757..8c1ef72f77d 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java @@ -101,9 +101,7 @@ public String getCampaignNameAndOid(AccessCertificationEvent event) { public void appendStatistics(StringBuilder sb, AccessCertificationCampaignType campaign, Task task, OperationResult result) { - sb.append("Number of cases:\t").append(campaign.getCase().size()); - - AccessCertificationCasesStatisticsType stat = null; + AccessCertificationCasesStatisticsType stat; try { stat = certificationManager.getCampaignStatistics(campaign.getOid(), false, task, result); } catch (ObjectNotFoundException|SchemaException|SecurityViolationException|ConfigurationException|CommunicationException|ObjectAlreadyExistsException|RuntimeException e) { @@ -111,6 +109,9 @@ public void appendStatistics(StringBuilder sb, AccessCertificationCampaignType c sb.append("Couldn't get campaign statistics because of ").append(e); return; } + int all = stat.getMarkedAsAccept() + stat.getMarkedAsRevoke() + stat.getMarkedAsReduce() + stat.getMarkedAsNotDecide() + + stat.getMarkedAsDelegate() + stat.getWithoutResponse(); + sb.append("Number of cases:\t").append(all); sb.append("\nMarked as ACCEPT:\t").append(stat.getMarkedAsAccept()); sb.append("\nMarked as REVOKE:\t").append(stat.getMarkedAsRevoke()) .append(" (remedied: ").append(stat.getMarkedAsRevokeAndRemedied()).append(")"); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 3126d1f7652..87dcdd7e53a 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql; +import com.evolveum.midpoint.common.filter.Filter; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContainerDefinition; @@ -52,8 +53,10 @@ import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; import com.evolveum.midpoint.schema.MidPointPrismContextFactory; import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.SchemaException; @@ -241,18 +244,6 @@ public void test010QueryOrganizationNorm() throws Exception { } } - private void assertEqualsIgnoreWhitespace(String expected, String real) { - LOGGER.info("exp. query>\n{}\nreal query>\n{}", expected, real); - String expNorm = StringUtils.normalizeSpace(expected); - String realNorm = StringUtils.normalizeSpace(real); - if (!expNorm.equals(realNorm)) { - String m = "Generated query is not correct. Expected:\n" + expected + "\nActual:\n" + real + "\n\nNormalized versions:\n\n" + - "Expected: " + expNorm + "\nActual: " + realNorm + "\n"; - LOGGER.error("{}", m); - throw new AssertionError(m); - } - } - @Test public void test011QueryOrganizationOrig() throws Exception { Session session = open(); @@ -2306,14 +2297,198 @@ public void test700QueryCertCaseAll() throws Exception { Session session = open(); try { String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, (ObjectQuery) null, false); - -// assertEqualsIgnoreWhitespace(expected, real); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test710QueryCertCaseOwner() throws Exception { + Session session = open(); + try { + InOidFilter filter = InOidFilter.createOwnerHasOidIn("123456"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + "where\n" + + " a.ownerOid in :ownerOid"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test720QueryCertCaseOwnerAndTarget() throws Exception { + Session session = open(); + try { + PrismContainerDefinition caseDef = + prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(AccessCertificationCaseType.class); + AndFilter filter = AndFilter.createAnd( + InOidFilter.createOwnerHasOidIn("123456"), + RefFilter.createReferenceEqual(new ItemPath(AccessCertificationCaseType.F_TARGET_REF), caseDef, "1234567890")); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + "where\n" + + " (\n" + + " a.ownerOid in :ownerOid and\n" + + " (\n" + + " a.targetRef.targetOid = :targetOid and\n" + + " a.targetRef.relation = :relation\n" + + " )\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test730QueryCertCaseReviewer() throws Exception { + Session session = open(); + try { + PrismContainerDefinition caseDef = + prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(AccessCertificationCaseType.class); + ObjectFilter filter = RefFilter.createReferenceEqual(new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), caseDef, "1234567890"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.reviewerRef r\n" + + "where\n" + + " (\n" + + " r.targetOid = :targetOid and\n" + + " r.relation = :relation\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + + @Test + public void test735QueryCertCaseReviewerAndEnabled() throws Exception { + Session session = open(); + try { + ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER); + ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( + new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), + AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); + ObjectFilter enabledFilter = EqualFilter.createEqual( + AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); + ObjectFilter filter = AndFilter.createAnd(reviewerFilter, enabledFilter); + + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.reviewerRef r\n" + + "where\n" + + " (\n" + + " (\n" + + " r.targetOid = :targetOid and\n" + + " r.relation = :relation and\n" + + " r.type = :type\n" + + " ) and\n" + + " a.enabled = :enabled\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test745QueryCertCaseReviewerAndEnabledByDeadlineAsc() throws Exception { + Session session = open(); + try { + ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER); + ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( + new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), + AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); + ObjectFilter enabledFilter = EqualFilter.createEqual( + AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); + ObjectFilter filter = AndFilter.createAnd(reviewerFilter, enabledFilter); + ObjectPaging paging = ObjectPaging.createPaging(new ItemPath(AccessCertificationCaseType.F_REVIEW_DEADLINE), OrderDirection.ASCENDING); + ObjectQuery query = ObjectQuery.createObjectQuery(filter, paging); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.reviewerRef r\n" + + "where\n" + + " (\n" + + " (\n" + + " r.targetOid = :targetOid and\n" + + " r.relation = :relation and\n" + + " r.type = :type\n" + + " ) and\n" + + " a.enabled = :enabled\n" + + " )\n" + + "order by a.reviewDeadline asc\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test + public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Exception { + Session session = open(); + try { + ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER); + ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( + new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), + AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); + ObjectFilter enabledFilter = EqualFilter.createEqual( + AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); + ObjectFilter filter = AndFilter.createAnd(reviewerFilter, enabledFilter); + ObjectPaging paging = ObjectPaging.createPaging(new ItemPath(AccessCertificationCaseType.F_REVIEW_REQUESTED_TIMESTAMP), OrderDirection.DESCENDING); + ObjectQuery query = ObjectQuery.createObjectQuery(filter, paging); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.reviewerRef r\n" + + "where\n" + + " (\n" + + " (\n" + + " r.targetOid = :targetOid and\n" + + " r.relation = :relation and\n" + + " r.type = :type\n" + + " ) and\n" + + " a.enabled = :enabled\n" + + " )\n" + + "order by a.reviewRequestedTimestamp desc"; + assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); } } + // TODO search for "no decision" condition (V2) + // TODO sorting based on referenced entity names (V2) + // TODO for cases: sorting based on object name, target name, campaign name (!) (V2-3) + protected String getInterpretedQuery2(Session session, Class type, File file) throws Exception { return getInterpretedQuery2(session, type, file, false); @@ -2359,4 +2534,17 @@ protected String getInterpretedQuery2(Session session, return ((RQueryImpl) rQuery).getQuery().getQueryString(); } + + private void assertEqualsIgnoreWhitespace(String expected, String real) { + LOGGER.info("exp. query>\n{}\nreal query>\n{}", expected, real); + String expNorm = StringUtils.normalizeSpace(expected); + String realNorm = StringUtils.normalizeSpace(real); + if (!expNorm.equals(realNorm)) { + String m = "Generated query is not correct. Expected:\n" + expected + "\nActual:\n" + real + "\n\nNormalized versions:\n\n" + + "Expected: " + expNorm + "\nActual: " + realNorm + "\n"; + LOGGER.error("{}", m); + throw new AssertionError(m); + } + } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index c5469a00a3f..15bbcbaeed3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -81,9 +81,11 @@ import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.SearchResultMetadata; import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; @@ -852,7 +854,7 @@ private void addCertificationCampaignCases(Session session, String campaignOid, for (PrismContainerValue value : values) { AccessCertificationCaseType caseType = new AccessCertificationCaseType(); caseType.setupContainerValue(value); - + caseType.setCampaignRef(ObjectTypeUtil.createObjectRef(campaignOid, ObjectTypes.ACCESS_CERTIFICATION_CAMPAIGN)); RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, getPrismContext()); row.setId(currentId); currentId++; @@ -898,7 +900,8 @@ private void updateLookupTableData(Session session, RObject object, Collection modifications) { + private void updateCampaignCases(Session session, RObject object, + Collection modifications) throws SchemaException { if (modifications.isEmpty()) { return; } @@ -909,31 +912,92 @@ private void updateCampaignCases(Session session, RObject object, Collection affectedIds = new ArrayList<>(); for (ItemDelta delta : modifications) { - if (!(delta instanceof ContainerDelta) || delta.getPath().size() != 1) { - throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + delta.getPath()); - } - // one "case" container modification - ContainerDelta containerDelta = (ContainerDelta) delta; - - if (containerDelta.getValuesToDelete() != null) { - // todo do 'bulk' delete like delete from ... where oid=? and id in (...) - for (PrismContainerValue value : (Collection) containerDelta.getValuesToDelete()) { - Query query = session.getNamedQuery("delete.campaignCase"); - query.setString("oid", campaignOid); - query.setInteger("id", RUtil.toInteger(value.getId())); - query.executeUpdate(); + ItemPath deltaPath = delta.getPath(); + if (!casePath.isSubPathOrEquivalent(deltaPath)) { + throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + deltaPath); + } + if (deltaPath.size() == 1) { + List ids = processWholeCaseModification(campaignOid, (ContainerDelta) delta, session); + if (affectedIds != null) { + if (ids != null) { + affectedIds.addAll(ids); + } else { + affectedIds = null; + } } + } else { + throw new UnsupportedOperationException(); // will be implemented later + } + } + LOGGER.trace("Affected ids = {}", affectedIds); + +// for (ItemDelta delta : modifications) { +// ItemPath deltaPath = delta.getPath(); +// if (deltaPath.size() > 1) { +// ItemPathSegment secondSegment = deltaPath.getSegments().get(1); +// if (!(secondSegment instanceof IdItemPathSegment)) { +// throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath); +// } +// Long id = ((IdItemPathSegment) secondSegment).getId(); +// if (id == null) { +// throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath); +// } +// if (deltaPath.size() == 2) { // not enough +// throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath); +// } +// if (affectedIds == null || affectedIds.contains(id)) { +// throw new IllegalArgumentException("Couldn't update certification case that was changed in this operation. Path=" + deltaPath); +// } +// +// +// +// delta.applyTo(prismObject); +// PrismContainer casesContainer = prismObject.findContainer(AccessCertificationCampaignType.F_CASE); +// if (casesContainer == null) { +// throw new IllegalStateException("No container for certification cases in campaign object " + campaignOid); +// } +// PrismContainerValue casePcv = casesContainer.getValue(id); +// if (casePcv == null) { +// throw new IllegalStateException("Certification case with id " + id + " was not found in campaign " + campaignOid); +// } +// RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(campaignOid, casePcv.asContainerable(), getPrismContext()); +// session.merge(rCase); +// } +// } + } + + // returns affected ids; null if replace was invoked + private List processWholeCaseModification(String campaignOid, ContainerDelta containerDelta, Session session) throws SchemaException { + List affectedIds = new ArrayList<>(); + + if (containerDelta.getValuesToDelete() != null) { + // todo do 'bulk' delete like delete from ... where oid=? and id in (...) + for (PrismContainerValue value : (Collection) containerDelta.getValuesToDelete()) { + Long id = value.getId(); + if (id == null) { + throw new SchemaException("Couldn't delete certification case with null id"); + } + affectedIds.add(id); + Query query = session.getNamedQuery("delete.campaignCase"); + query.setString("oid", campaignOid); + query.setInteger("id", RUtil.toInteger(id)); + query.executeUpdate(); } - if (containerDelta.getValuesToAdd() != null) { - int currentId = findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; - addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToAdd(), currentId); - } - if (containerDelta.getValuesToReplace() != null) { - deleteCertificationCampaignCases(session, campaignOid); - addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToReplace(), 1); - } } + if (containerDelta.getValuesToAdd() != null) { + int currentId = findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; + affectedIds.add((long) currentId); + addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToAdd(), currentId); + } + if (containerDelta.getValuesToReplace() != null) { + deleteCertificationCampaignCases(session, campaignOid); + addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToReplace(), 1); + affectedIds = null; + } + return affectedIds; } private int findLastIdInRepo(Session session, String tableOid, String queryName) { @@ -1197,8 +1261,8 @@ private SearchResultList searchContainersAttempt(Cl LOGGER.trace("Found {} items, translating to JAXB.", items.size()); for (GetObjectResult item : items) { - PrismContainerValue cvalue = (PrismContainerValue) updateLoadedCertificationCase(item, options, session); - list.add(cvalue.asContainerable()); + C value = (C) updateLoadedCertificationCase(item, options, session); + list.add(value); } session.getTransaction().commit(); @@ -1320,14 +1384,13 @@ public void visit(Visitable visitable) { } - private PrismContainerValue updateLoadedCertificationCase(GetObjectResult result, - Collection> options, - Session session) throws SchemaException { + private AccessCertificationCaseType updateLoadedCertificationCase(GetObjectResult result, + Collection> options, + Session session) throws SchemaException { AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), getPrismContext()); - PrismContainerValue cvalue = aCase.asPrismContainerValue(); - validateContainerValue(cvalue, AccessCertificationCaseType.class); - return cvalue; + validateContainerable(aCase, AccessCertificationCaseType.class); + return aCase; } @@ -1734,7 +1797,8 @@ private Collection filterCampaignCas caseDelta.add(delta); } else if (path.isSuperPath(casePath)) { // todo - what about modifications with path like case[id] or case[id]/xxx? - throw new UnsupportedOperationException("Campaign case can be modified only by specifying path=case"); + throw new UnsupportedOperationException("Campaign case can be modified only by specifying path=case; not via " + path); + //caseDelta.add(delta); } } @@ -1885,12 +1949,12 @@ private void validateObjectType(PrismObject prismObjec } } - private void validateContainerValue(PrismContainerValue cvalue, Class type) + private void validateContainerable(C value, Class type) throws SchemaException { - if (cvalue == null) { + if (value == null) { throw new SchemaException("Null object as a result of repository get operation for " + type); } - Class realType = cvalue.asContainerable().getClass(); + Class realType = value.getClass(); if (!type.isAssignableFrom(realType)) { throw new SchemaException("Expected to find '" + type.getSimpleName() + "' but found '" + realType.getSimpleName()); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 281789bde08..fb661447e46 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; @@ -78,6 +79,9 @@ public void setDefinitionRef(REmbeddedReference definitionRef) { @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getCases() { + if (cases == null) { + cases = new HashSet(); + } return cases; } @@ -121,8 +125,8 @@ public static void copyFromJAXB(AccessCertificationCampaignType jaxb, RAccessCer List cases = jaxb.getCase(); if (!cases.isEmpty()) { - repo.setCases(new HashSet()); for (AccessCertificationCaseType case1 : cases) { + case1.setCampaignRef(ObjectTypeUtil.createObjectRef(jaxb)); RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(repo, case1, prismContext); rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); repo.getCases().add(rCase); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 44847bf55df..5dd144e6c72 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -28,29 +28,20 @@ import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.Validate; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Where; -import javax.persistence.Column; -import javax.persistence.Embedded; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.Index; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.MapsId; -import javax.persistence.OneToMany; -import javax.persistence.Table; +import javax.persistence.*; +import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import java.util.Arrays; import java.util.HashSet; @@ -86,6 +77,13 @@ public class RAccessCertificationCase implements Container { private REmbeddedNamedReference objectRef; private REmbeddedNamedReference targetRef; + private boolean enabled; + private XMLGregorianCalendar reviewRequestedTimestamp; + private XMLGregorianCalendar reviewDeadline; + private XMLGregorianCalendar remediedTimestamp; + // TODO: private Set decisions; + // TODO: currentResponse, currentResponseStage + public RAccessCertificationCase() { this(null); } @@ -146,6 +144,22 @@ public REmbeddedNamedReference getObjectRef() { return objectRef; } + public boolean isEnabled() { + return enabled; + } + + public XMLGregorianCalendar getReviewRequestedTimestamp() { + return reviewRequestedTimestamp; + } + + public XMLGregorianCalendar getReviewDeadline() { + return reviewDeadline; + } + + public XMLGregorianCalendar getRemediedTimestamp() { + return remediedTimestamp; + } + public void setOwner(RObject owner) { this.owner = owner; } @@ -166,6 +180,22 @@ public void setObjectRef(REmbeddedNamedReference objectRef) { this.objectRef = objectRef; } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setReviewRequestedTimestamp(XMLGregorianCalendar reviewRequestedTimestamp) { + this.reviewRequestedTimestamp = reviewRequestedTimestamp; + } + + public void setReviewDeadline(XMLGregorianCalendar reviewDeadline) { + this.reviewDeadline = reviewDeadline; + } + + public void setRemediedTimestamp(XMLGregorianCalendar remediedTimestamp) { + this.remediedTimestamp = remediedTimestamp; + } + @Lob public byte[] getFullObject() { return fullObject; @@ -178,39 +208,55 @@ public void setFullObject(byte[] fullObject) { @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof RAccessCertificationCase)) return false; RAccessCertificationCase that = (RAccessCertificationCase) o; + if (enabled != that.enabled) return false; + if (!Arrays.equals(fullObject, that.fullObject)) return false; + if (ownerOid != null ? !ownerOid.equals(that.ownerOid) : that.ownerOid != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; if (reviewerRef != null ? !reviewerRef.equals(that.reviewerRef) : that.reviewerRef != null) return false; - if (targetRef != null ? !targetRef.equals(that.targetRef) : that.targetRef != null) return false; if (objectRef != null ? !objectRef.equals(that.objectRef) : that.objectRef != null) return false; - if (fullObject != null ? !Arrays.equals(fullObject, that.fullObject) : that.fullObject != null) return false; - - return true; + if (targetRef != null ? !targetRef.equals(that.targetRef) : that.targetRef != null) return false; + if (reviewRequestedTimestamp != null ? !reviewRequestedTimestamp.equals(that.reviewRequestedTimestamp) : that.reviewRequestedTimestamp != null) + return false; + if (reviewDeadline != null ? !reviewDeadline.equals(that.reviewDeadline) : that.reviewDeadline != null) + return false; + return !(remediedTimestamp != null ? !remediedTimestamp.equals(that.remediedTimestamp) : that.remediedTimestamp != null); } @Override public int hashCode() { - int result = super.hashCode(); - result = 31 * result + (targetRef != null ? targetRef.hashCode() : 0); + int result = ownerOid != null ? ownerOid.hashCode() : 0; + result = 31 * result + (id != null ? id.hashCode() : 0); + result = 31 * result + (reviewerRef != null ? reviewerRef.hashCode() : 0); result = 31 * result + (objectRef != null ? objectRef.hashCode() : 0); + result = 31 * result + (targetRef != null ? targetRef.hashCode() : 0); + result = 31 * result + (enabled ? 1 : 0); + result = 31 * result + (reviewRequestedTimestamp != null ? reviewRequestedTimestamp.hashCode() : 0); + result = 31 * result + (reviewDeadline != null ? reviewDeadline.hashCode() : 0); + result = 31 * result + (remediedTimestamp != null ? remediedTimestamp.hashCode() : 0); return result; } - public static void copyFromJAXB(AccessCertificationCaseType jaxb, RAccessCertificationCase repo, ObjectType parent, PrismContext prismContext, - IdGeneratorResult generatorResult) throws DtoTranslationException { - Validate.notNull(repo, "Repo object must not be null."); - Validate.notNull(jaxb, "JAXB object must not be null."); - - repo.setOwnerOid(parent.getOid()); - repo.setId(RUtil.toInteger(jaxb.getId())); - - repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getTargetRef(), prismContext)); - repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getObjectRef(), prismContext)); - repo.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( - jaxb.getReviewerRef(), prismContext, repo, RCReferenceOwner.CASE_REVIEWER)); - } +// public static void copyFromJAXB(AccessCertificationCaseType jaxb, RAccessCertificationCase repo, ObjectType parent, PrismContext prismContext, +// IdGeneratorResult generatorResult) throws DtoTranslationException { +// Validate.notNull(repo, "Repo object must not be null."); +// Validate.notNull(jaxb, "JAXB object must not be null."); +// +// repo.setOwnerOid(parent.getOid()); +// repo.setId(RUtil.toInteger(jaxb.getId())); +// +// repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getTargetRef(), prismContext)); +// repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getObjectRef(), prismContext)); +// repo.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( +// jaxb.getReviewerRef(), prismContext, repo, RCReferenceOwner.CASE_REVIEWER)); +// repo.setEnabled(BooleanUtils.isTrue(jaxb.isEnabled())); +// repo.setReviewRequestedTimestamp(jaxb.getReviewRequestedTimestamp()); +// repo.setReviewDeadline(jaxb.getReviewDeadline()); +// repo.setRemediedTimestamp(jaxb.getRemediedTimestamp()); +// } @Override public String toString() { @@ -224,6 +270,7 @@ public String toString() { } @Override + @Transient public Boolean isTransient() { return trans; } @@ -252,6 +299,10 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 rCase.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getTargetRef(), prismContext)); rCase.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( case1.getReviewerRef(), prismContext, rCase, RCReferenceOwner.CASE_REVIEWER)); + rCase.setEnabled(case1.isEnabled()); + rCase.setReviewRequestedTimestamp(case1.getReviewRequestedTimestamp()); + rCase.setReviewDeadline(case1.getReviewDeadline()); + rCase.setRemediedTimestamp(case1.getRemediedTimestamp()); String xml; try { xml = prismContext.serializeContainerValueToString(case1.asPrismContainerValue(), new QName("value"), PrismContext.LANG_XML); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index ee696ab7ebd..8a5d1ae88ef 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -120,4 +120,8 @@ public InterpreterHelper getHelper() { public EntityDefinition getRootEntityDefinition() { return rootEntityDefinition; } + + public boolean isObject() { + return ObjectType.class.isAssignableFrom(type); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index d328ba701be..0bd168088c9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -156,12 +156,14 @@ public RootHibernateQuery interpret(ObjectQuery query, Class idValues; + + // TODO check applicability + if (filter.isConsiderOwner()) { + hqlPath += "ownerOid"; + idValues = filter.getOids(); + } else if (ObjectType.class.isAssignableFrom(baseEntityDefinition.getJaxbType())) { + hqlPath += "oid"; + idValues = filter.getOids(); + } else if (Containerable.class.isAssignableFrom(baseEntityDefinition.getJaxbType())) { + hqlPath += "id"; // quite a hack + idValues = toIntList(filter.getOids()); + } else { + throw new QueryException("InOidRestriction cannot be applied to the entity: " + baseEntityDefinition); + } + + return getContext().getHibernateQuery().createIn(hqlPath, idValues); + } + + private Collection toIntList(Collection ids) { + List rv = new ArrayList<>(); + for (String id : ids) { + rv.add(Integer.parseInt(id)); + } + return rv; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java index 3df6ba38d1e..a0626e17e1e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -42,6 +42,7 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.apache.commons.lang.ClassUtils; import javax.xml.namespace.QName; import java.util.List; @@ -138,26 +139,31 @@ protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); } + Class expectedType = def.getJaxbType(); + if (expectedType.isPrimitive()) { + expectedType = ClassUtils.primitiveToWrapper(expectedType); + } + //todo remove after some time [lazyman] //attempt to fix value type for polystring (if it was string in filter we create polystring from it) - if (PolyString.class.equals(def.getJaxbType()) && (value instanceof String)) { + if (PolyString.class.equals(expectedType) && (value instanceof String)) { LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", new Object[]{filter}); value = new PolyString((String) value, (String) value); } //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) - if (PolyString.class.equals(def.getJaxbType()) && (value instanceof PolyStringType)) { + if (PolyString.class.equals(expectedType) && (value instanceof PolyStringType)) { LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", new Object[]{filter}); PolyStringType type = (PolyStringType) value; value = new PolyString(type.getOrig(), type.getNorm()); } - if (String.class.equals(def.getJaxbType()) && (value instanceof QName)) { + if (String.class.equals(expectedType) && (value instanceof QName)) { //eg. shadow/objectClass value = RUtil.qnameToString((QName) value); } - if (value != null && !def.getJaxbType().isAssignableFrom(value.getClass())) { - throw new QueryException("Value should be type of '" + def.getJaxbType() + "' but it's '" + if (value != null && !expectedType.isAssignableFrom(value.getClass())) { + throw new QueryException("Value should be type of '" + expectedType + "' but it's '" + value.getClass() + "', filter '" + filter + "'."); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/GetObjectResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/GetObjectResult.java index 65b728cb7d7..dbf8e78c147 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/GetObjectResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/GetObjectResult.java @@ -33,8 +33,13 @@ public Object transformTuple(Object[] tuple, String[] aliases) { private Short booleansCount; public GetObjectResult(Object[] values) { - this((byte[]) values[0], (Short) values[1], (Short) values[2], (Short) values[3], - (Short) values[4], (Short) values[5], (Short) values[6]); + this((byte[]) values[0], + values.length > 1 ? (Short) values[1] : null, + values.length > 2 ? (Short) values[2] : null, + values.length > 3 ? (Short) values[3] : null, + values.length > 4 ? (Short) values[4] : null, + values.length > 5 ? (Short) values[5] : null, + values.length > 6 ? (Short) values[6] : null); } public GetObjectResult(byte[] fullObject, Short stringsCount, Short longsCount, Short datesCount, From 491f702a394ec66a90aa4cc10031cb3c3b5a5142 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 26 Nov 2015 10:59:31 +0100 Subject: [PATCH 018/116] Implemented case content modifications. Factored out lookup table and cert case support to separate helper classes. --- .../midpoint/prism/delta/ItemDelta.java | 9 + .../prism/parser/XNodeSerializer.java | 9 +- .../midpoint/prism/path/ItemPath.java | 12 +- .../test/BasicCertificationTest.java | 2 +- .../repo/sql/SqlRepositoryServiceImpl.java | 476 +----------------- .../repo/sql/data/common/RObject.java | 1 + .../container/RAccessCertificationCase.java | 4 +- .../sql/helpers/CertificationCaseHelper.java | 276 ++++++++++ .../repo/sql/helpers/GeneralHelper.java | 59 +++ .../repo/sql/helpers/LookupTableHelper.java | 284 +++++++++++ 10 files changed, 672 insertions(+), 460 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java index 405c574ca9e..df9315640da 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java @@ -1081,6 +1081,15 @@ public static void applyToMatchingPath(Collection deltas, P delta.applyToMatchingPath(propertyContainer); } } + + public void applyTo(PrismContainerValue containerValue) throws SchemaException { + ItemPath deltaPath = getPath(); + if (ItemPath.isNullOrEmpty(deltaPath)) { + throw new IllegalArgumentException("Cannot apply empty-path delta " + this + " directly to a PrismContainerValue " + containerValue); + } + Item subItem = containerValue.findOrCreateItem(deltaPath, getItemClass(), getDefinition()); + applyToMatchingPath(subItem); + } public void applyTo(Item item) throws SchemaException { ItemPath itemPath = item.getPath(); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XNodeSerializer.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XNodeSerializer.java index eb13ffcd4a5..717f4c43e32 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XNodeSerializer.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XNodeSerializer.java @@ -137,14 +137,19 @@ public XNode serializeItem(Ite public RootXNode serializeItemValueAsRoot(PrismValue value, QName elementName) throws SchemaException { Validate.notNull(value, "Item value to be serialized cannot be null"); - Validate.notNull(value.getParent(), "Item value to be serialized must have a parent"); + //Validate.notNull(value.getParent(), "Item value to be serialized must have a parent"); Validate.notNull(elementName, "Element name cannot be null"); return serializeItemValueAsRootInternal(value, elementName); } // element name may be null (it is then derived from the definition, if the definition exists) private RootXNode serializeItemValueAsRootInternal(PrismValue value, QName elementName) throws SchemaException { - ItemDefinition definition = value.getParent().getDefinition(); // the definition may be null here + ItemDefinition definition; + if (value.getParent() != null) { + definition = value.getParent().getDefinition(); // the definition may be null here + } else { + definition = null; + } XNode valueNode = serializeItemValue(value, definition); if (elementName == null) { if (definition == null) { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index dedc0118276..a700a265d8d 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -184,13 +184,17 @@ public ItemPath head() { } /** - * Returns path containinig all segments except the first. + * Returns path containing all segments except the first N. */ - public ItemPath tail() { - if (segments.size() == 0) { + public ItemPath tail(int n) { + if (segments.size() < n) { return EMPTY_PATH; } - return new ItemPath(segments.subList(1, segments.size())); + return new ItemPath(segments.subList(n, segments.size())); + } + + public ItemPath tail() { + return tail(1); } /** diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java index d1783dd7b98..5a99563c530 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java @@ -203,7 +203,7 @@ public void test030SearchAllCases() throws Exception { checkAllCases(caseList); } - @Test + @Test(enabled = false) public void test040SearchCasesFilteredSortedPaged() throws Exception { final String TEST_NAME = "test040SearchCasesFilteredSortedPaged"; TestUtil.displayTestTile(this, TEST_NAME); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 15bbcbaeed3..3731f9fb558 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -22,7 +22,6 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; @@ -34,16 +33,13 @@ import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; -import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.parser.XNodeProcessorEvaluationMode; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.polystring.PrismDefaultPolyStringNormalizer; import com.evolveum.midpoint.prism.query.AllFilter; import com.evolveum.midpoint.prism.query.NoneFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; @@ -51,15 +47,14 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.repo.api.RepositoryService; -import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; -import com.evolveum.midpoint.repo.sql.data.common.RLookupTable; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.data.common.any.RValueType; -import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; -import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.helpers.CertificationCaseHelper; +import com.evolveum.midpoint.repo.sql.helpers.LookupTableHelper; +import com.evolveum.midpoint.repo.sql.helpers.GeneralHelper; import com.evolveum.midpoint.repo.sql.query.QueryEngine; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.RQuery; @@ -73,19 +68,15 @@ import com.evolveum.midpoint.repo.sql.util.ScrollableResultsIterator; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.LabeledString; -import com.evolveum.midpoint.schema.ObjectSelector; -import com.evolveum.midpoint.schema.RelationalValueSearchQuery; import com.evolveum.midpoint.schema.RepositoryDiag; import com.evolveum.midpoint.schema.ResultHandler; import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.SearchResultMetadata; import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; @@ -96,7 +87,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; @@ -113,7 +103,6 @@ import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.Session; -import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.internal.SessionFactoryImpl; @@ -162,6 +151,11 @@ public class SqlRepositoryServiceImpl extends SqlBaseService implements Reposito private static final String DETAILS_HIBERNATE_DIALECT = "hibernateDialect"; private static final String DETAILS_HIBERNATE_HBM_2_DDL = "hibernateHbm2ddl"; + // initialized in post-construct method + private GeneralHelper generalHelper; + private LookupTableHelper lookupTableHelper; + private CertificationCaseHelper caseHelper; + private OrgClosureManager closureManager; public SqlRepositoryServiceImpl(SqlRepositoryFactory repositoryFactory) { @@ -625,8 +619,8 @@ private String overwriteAddObjectAttempt(PrismObject o updateFullObject(rObject, object); RObject merged = (RObject) session.merge(rObject); - addLookupTableRows(session, rObject, modifications != null); - addCertificationCampaignCases(session, rObject, modifications != null); + lookupTableHelper.addLookupTableRows(session, rObject, modifications != null); + caseHelper.addCertificationCampaignCases(session, rObject, modifications != null); if (getClosureManager().isEnabled()) { OrgClosureManager.Operation operation; @@ -691,8 +685,8 @@ private String nonOverwriteAddObjectAttempt(PrismObject modifications = createAddParentRefDelta(object); @@ -772,10 +766,10 @@ private void deleteObjectAttempt(Class type, String oi session.delete(object); if (LookupTableType.class.equals(type)) { - deleteLookupTableRows(session, oid); + lookupTableHelper.deleteLookupTableRows(session, oid); } if (AccessCertificationCampaignType.class.equals(type)) { - deleteCertificationCampaignCases(session, oid); + caseHelper.deleteCertificationCampaignCases(session, oid); } session.getTransaction().commit(); @@ -789,227 +783,6 @@ private void deleteObjectAttempt(Class type, String oi } } - /** - * This method removes all lookup table rows for object defined by oid - */ - private void deleteLookupTableRows(Session session, String oid) { - Query query = session.getNamedQuery("delete.lookupTableData"); - query.setParameter("oid", oid); - - query.executeUpdate(); - } - - private void addLookupTableRows(Session session, RObject object, boolean merge) { - if (!(object instanceof RLookupTable)) { - return; - } - RLookupTable table = (RLookupTable) object; - - if (merge) { - deleteLookupTableRows(session, table.getOid()); - } - if (table.getRows() != null) { - for (RLookupTableRow row : table.getRows()) { - session.save(row); - } - } - } - - private void deleteCertificationCampaignCases(Session session, String oid) { - Query query = session.getNamedQuery("delete.campaignCases"); - query.setParameter("oid", oid); - - query.executeUpdate(); - } - - private void addCertificationCampaignCases(Session session, RObject object, boolean merge) { - if (!(object instanceof RAccessCertificationCampaign)) { - return; - } - RAccessCertificationCampaign campaign = (RAccessCertificationCampaign) object; - - if (merge) { - deleteCertificationCampaignCases(session, campaign.getOid()); - } - if (campaign.getCases() != null) { - for (RAccessCertificationCase aCase : campaign.getCases()) { - session.save(aCase); - } - } - } - - private void addLookupTableRows(Session session, String tableOid, Collection values, int currentId) { - for (PrismContainerValue value : values) { - LookupTableRowType rowType = new LookupTableRowType(); - rowType.setupContainerValue(value); - - RLookupTableRow row = RLookupTableRow.toRepo(tableOid, rowType); - row.setId(currentId); - currentId++; - session.save(row); - } - } - - private void addCertificationCampaignCases(Session session, String campaignOid, Collection values, int currentId) { - for (PrismContainerValue value : values) { - AccessCertificationCaseType caseType = new AccessCertificationCaseType(); - caseType.setupContainerValue(value); - caseType.setCampaignRef(ObjectTypeUtil.createObjectRef(campaignOid, ObjectTypes.ACCESS_CERTIFICATION_CAMPAIGN)); - RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, getPrismContext()); - row.setId(currentId); - currentId++; - session.save(row); - } - } - - private void updateLookupTableData(Session session, RObject object, Collection modifications) { - if (modifications.isEmpty()) { - return; - } - - if (!(object instanceof RLookupTable)) { - throw new IllegalStateException("Object being modified is not a LookupTable; it is " + object.getClass()); - } - final RLookupTable rLookupTable = (RLookupTable) object; - final String tableOid = object.getOid(); - - for (ItemDelta delta : modifications) { - if (!(delta instanceof ContainerDelta) || delta.getPath().size() != 1) { - throw new IllegalStateException("Wrong table delta sneaked into updateLookupTableData: class=" + delta.getClass() + ", path=" + delta.getPath()); - } - // one "table" container modification - ContainerDelta containerDelta = (ContainerDelta) delta; - - if (containerDelta.getValuesToDelete() != null) { - // todo do 'bulk' delete like delete from ... where oid=? and id in (...) - for (PrismContainerValue value : (Collection) containerDelta.getValuesToDelete()) { - Query query = session.getNamedQuery("delete.lookupTableDataRow"); - query.setString("oid", tableOid); - query.setInteger("id", RUtil.toInteger(value.getId())); - query.executeUpdate(); - } - } - if (containerDelta.getValuesToAdd() != null) { - int currentId = findLastIdInRepo(session, tableOid, "get.lookupTableLastId") + 1; - addLookupTableRows(session, tableOid, containerDelta.getValuesToAdd(), currentId); - } - if (containerDelta.getValuesToReplace() != null) { - deleteLookupTableRows(session, tableOid); - addLookupTableRows(session, tableOid, containerDelta.getValuesToReplace(), 1); - } - } - } - - private void updateCampaignCases(Session session, RObject object, - Collection modifications) throws SchemaException { - if (modifications.isEmpty()) { - return; - } - - if (!(object instanceof RAccessCertificationCampaign)) { - throw new IllegalStateException("Object being modified is not a RAccessCertificationCampaign; it is " + object.getClass()); - } - final RAccessCertificationCampaign rCampaign = (RAccessCertificationCampaign) object; - final String campaignOid = object.getOid(); - - final ItemPath casePath = new ItemPath(AccessCertificationCampaignType.F_CASE); - List affectedIds = new ArrayList<>(); - for (ItemDelta delta : modifications) { - ItemPath deltaPath = delta.getPath(); - if (!casePath.isSubPathOrEquivalent(deltaPath)) { - throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + deltaPath); - } - if (deltaPath.size() == 1) { - List ids = processWholeCaseModification(campaignOid, (ContainerDelta) delta, session); - if (affectedIds != null) { - if (ids != null) { - affectedIds.addAll(ids); - } else { - affectedIds = null; - } - } - } else { - throw new UnsupportedOperationException(); // will be implemented later - } - } - LOGGER.trace("Affected ids = {}", affectedIds); - -// for (ItemDelta delta : modifications) { -// ItemPath deltaPath = delta.getPath(); -// if (deltaPath.size() > 1) { -// ItemPathSegment secondSegment = deltaPath.getSegments().get(1); -// if (!(secondSegment instanceof IdItemPathSegment)) { -// throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath); -// } -// Long id = ((IdItemPathSegment) secondSegment).getId(); -// if (id == null) { -// throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath); -// } -// if (deltaPath.size() == 2) { // not enough -// throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath); -// } -// if (affectedIds == null || affectedIds.contains(id)) { -// throw new IllegalArgumentException("Couldn't update certification case that was changed in this operation. Path=" + deltaPath); -// } -// -// -// -// delta.applyTo(prismObject); -// PrismContainer casesContainer = prismObject.findContainer(AccessCertificationCampaignType.F_CASE); -// if (casesContainer == null) { -// throw new IllegalStateException("No container for certification cases in campaign object " + campaignOid); -// } -// PrismContainerValue casePcv = casesContainer.getValue(id); -// if (casePcv == null) { -// throw new IllegalStateException("Certification case with id " + id + " was not found in campaign " + campaignOid); -// } -// RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(campaignOid, casePcv.asContainerable(), getPrismContext()); -// session.merge(rCase); -// } -// } - } - - // returns affected ids; null if replace was invoked - private List processWholeCaseModification(String campaignOid, ContainerDelta containerDelta, Session session) throws SchemaException { - List affectedIds = new ArrayList<>(); - - if (containerDelta.getValuesToDelete() != null) { - // todo do 'bulk' delete like delete from ... where oid=? and id in (...) - for (PrismContainerValue value : (Collection) containerDelta.getValuesToDelete()) { - Long id = value.getId(); - if (id == null) { - throw new SchemaException("Couldn't delete certification case with null id"); - } - affectedIds.add(id); - Query query = session.getNamedQuery("delete.campaignCase"); - query.setString("oid", campaignOid); - query.setInteger("id", RUtil.toInteger(id)); - query.executeUpdate(); - } - } - if (containerDelta.getValuesToAdd() != null) { - int currentId = findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; - affectedIds.add((long) currentId); - addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToAdd(), currentId); - } - if (containerDelta.getValuesToReplace() != null) { - deleteCertificationCampaignCases(session, campaignOid); - addCertificationCampaignCases(session, campaignOid, containerDelta.getValuesToReplace(), 1); - affectedIds = null; - } - return affectedIds; - } - - private int findLastIdInRepo(Session session, String tableOid, String queryName) { - Query query = session.getNamedQuery(queryName); - query.setString("oid", tableOid); - Integer lastId = (Integer) query.uniqueResult(); - if (lastId == null) { - lastId = 0; - } - return lastId; - } - @Override public int countObjects(Class type, ObjectQuery query, OperationResult result) { Validate.notNull(type, "Object type must not be null."); @@ -1261,7 +1034,7 @@ private SearchResultList searchContainersAttempt(Cl LOGGER.trace("Found {} items, translating to JAXB.", items.size()); for (GetObjectResult item : items) { - C value = (C) updateLoadedCertificationCase(item, options, session); + C value = (C) caseHelper.updateLoadedCertificationCase(item, options, session); list.add(value); } @@ -1325,9 +1098,9 @@ private PrismObject updateLoadedObject(GetObjectResult } LOGGER.debug("Definitions for attributes loaded. Counts: {}", Arrays.toString(counts)); } else if (LookupTableType.class.equals(prismObject.getCompileTimeClass())) { - updateLoadedLookupTable(prismObject, options, session); + lookupTableHelper.updateLoadedLookupTable(prismObject, options, session); } else if (AccessCertificationCampaignType.class.equals(prismObject.getCompileTimeClass())) { - updateLoadedCampaign(prismObject, options, session); + caseHelper.updateLoadedCampaign(prismObject, options, session); } GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); @@ -1384,16 +1157,6 @@ public void visit(Visitable visitable) { } - private AccessCertificationCaseType updateLoadedCertificationCase(GetObjectResult result, - Collection> options, - Session session) throws SchemaException { - - AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), getPrismContext()); - validateContainerable(aCase, AccessCertificationCaseType.class); - return aCase; - } - - private Map consolidateResults(List> results){ Map oidNameMap = new HashMap(); for (Map map : results){ @@ -1403,137 +1166,6 @@ private Map consolidateResults(List> res return oidNameMap; } - private GetOperationOptions findLookupTableGetOption(Collection> options) { - final ItemPath tablePath = new ItemPath(LookupTableType.F_ROW); - - Collection> filtered = SelectorOptions.filterRetrieveOptions(options); - for (SelectorOptions option : filtered) { - ObjectSelector selector = option.getSelector(); - if (selector == null) { - // Ignore this. These are top-level options. There will not - // apply to lookup table - continue; - } - ItemPath selected = selector.getPath(); - - if (tablePath.equivalent(selected)) { - return option.getOptions(); - } - } - - return null; - } - - private void updateLoadedLookupTable(PrismObject object, - Collection> options, - Session session) throws SchemaException { - if (!SelectorOptions.hasToLoadPath(LookupTableType.F_ROW, options)) { - return; - } - - LOGGER.debug("Loading lookup table data."); - - GetOperationOptions getOption = findLookupTableGetOption(options); - RelationalValueSearchQuery queryDef = getOption == null ? null : getOption.getRelationalValueSearchQuery(); - Criteria criteria = setupLookupTableRowsQuery(session, queryDef, object.getOid()); - if (queryDef != null && queryDef.getPaging() != null) { - ObjectPaging paging = queryDef.getPaging(); - - if (paging.getOffset() != null) { - criteria.setFirstResult(paging.getOffset()); - } - if (paging.getMaxSize() != null) { - criteria.setMaxResults(paging.getMaxSize()); - } - - ItemPath orderByPath = paging.getOrderBy(); - if (paging.getDirection() != null && orderByPath != null && !orderByPath.isEmpty()) { - if (orderByPath.size() > 1 || !(orderByPath.first() instanceof NameItemPathSegment)) { - throw new SchemaException("OrderBy has to consist of just one naming segment"); - } - String orderBy = ((NameItemPathSegment) (orderByPath.first())).getName().getLocalPart(); - switch (paging.getDirection()) { - case ASCENDING: - criteria.addOrder(Order.asc(orderBy)); - break; - case DESCENDING: - criteria.addOrder(Order.desc(orderBy)); - break; - } - } - } - - List rows = criteria.list(); - if (rows == null || rows.isEmpty()) { - return; - } - - LookupTableType lookup = (LookupTableType) object.asObjectable(); - List jaxbRows = lookup.getRow(); - for (RLookupTableRow row : rows) { - LookupTableRowType jaxbRow = row.toJAXB(); - jaxbRows.add(jaxbRow); - } - } - - private void updateLoadedCampaign(PrismObject object, - Collection> options, - Session session) throws SchemaException { - if (!SelectorOptions.hasToLoadPath(AccessCertificationCampaignType.F_CASE, options)) { - return; - } - - LOGGER.debug("Loading certification campaign cases."); - - Criteria criteria = session.createCriteria(RAccessCertificationCase.class); - criteria.add(Restrictions.eq("ownerOid", object.getOid())); - - List cases = criteria.list(); - if (cases == null || cases.isEmpty()) { - return; - } - - AccessCertificationCampaignType campaign = (AccessCertificationCampaignType) object.asObjectable(); - List jaxbCases = campaign.getCase(); - for (RAccessCertificationCase rCase : cases) { - AccessCertificationCaseType jaxbCase = rCase.toJAXB(getPrismContext()); - jaxbCases.add(jaxbCase); - } - } - - private Criteria setupLookupTableRowsQuery(Session session, RelationalValueSearchQuery queryDef, String oid) { - Criteria criteria = session.createCriteria(RLookupTableRow.class); - criteria.add(Restrictions.eq("ownerOid", oid)); - - if (queryDef != null - && queryDef.getColumn() != null - && queryDef.getSearchType() != null - && StringUtils.isNotEmpty(queryDef.getSearchValue())) { - - String param = queryDef.getColumn().getLocalPart(); - String value = queryDef.getSearchValue(); - if (LookupTableRowType.F_LABEL.equals(queryDef.getColumn())) { - param = "label.norm"; - - PolyString poly = new PolyString(value); - poly.recompute(new PrismDefaultPolyStringNormalizer()); - value = poly.getNorm(); - } - switch (queryDef.getSearchType()) { - case EXACT: - criteria.add(Restrictions.eq(param, value)); - break; - case STARTS_WITH: - criteria.add(Restrictions.like(param, value + "%")); - break; - case SUBSTRING: - criteria.add(Restrictions.like(param, "%" + value + "%")); - } - } - - return criteria; - } - private void applyShadowAttributeDefinitions(Class anyValueType, PrismObject object, Session session) throws SchemaException { @@ -1661,8 +1293,8 @@ private void modifyObjectAttempt(Class type, String oi closureContext = getClosureManager().onBeginTransactionModify(session, type, oid, modifications); - Collection lookupTableModifications = filterLookupTableModifications(type, modifications); - Collection campaignCaseModifications = filterCampaignCaseModifications(type, modifications); + Collection lookupTableModifications = lookupTableHelper.filterLookupTableModifications(type, modifications); + Collection campaignCaseModifications = caseHelper.filterCampaignCaseModifications(type, modifications); // JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big. // Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo @@ -1712,8 +1344,8 @@ private void modifyObjectAttempt(Class type, String oi updateFullObject(rObject, prismObject); session.merge(rObject); - updateLookupTableData(session, rObject, lookupTableModifications); - updateCampaignCases(session, rObject, campaignCaseModifications); + lookupTableHelper.updateLookupTableData(session, rObject, lookupTableModifications); + caseHelper.updateCampaignCases(session, rObject, campaignCaseModifications); if (getClosureManager().isEnabled()) { getClosureManager().updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext); @@ -1756,57 +1388,6 @@ private void modifyObjectAttempt(Class type, String oi } } - private Collection filterLookupTableModifications(Class type, - Collection modifications) { - Collection tableDelta = new ArrayList<>(); - if (!LookupTableType.class.equals(type)) { - return tableDelta; - } - - ItemPath tablePath = new ItemPath(LookupTableType.F_ROW); - for (ItemDelta delta : modifications) { - ItemPath path = delta.getPath(); - if (path.isEmpty()) { - throw new UnsupportedOperationException("Lookup table cannot be modified via empty-path modification"); - } else if (path.equivalent(tablePath)) { - tableDelta.add(delta); - } else if (path.isSuperPath(tablePath)) { - // todo - what about modifications with path like table[id] or table[id]/xxx where xxx=key|value|label? - throw new UnsupportedOperationException("Lookup table row can be modified only by specifying path=table"); - } - } - - modifications.removeAll(tableDelta); - - return tableDelta; - } - - private Collection filterCampaignCaseModifications(Class type, - Collection modifications) { - Collection caseDelta = new ArrayList<>(); - if (!AccessCertificationCampaignType.class.equals(type)) { - return caseDelta; - } - - ItemPath casePath = new ItemPath(AccessCertificationCampaignType.F_CASE); - for (ItemDelta delta : modifications) { - ItemPath path = delta.getPath(); - if (path.isEmpty()) { - throw new UnsupportedOperationException("Certification campaign cannot be modified via empty-path modification"); - } else if (path.equivalent(casePath)) { - caseDelta.add(delta); - } else if (path.isSuperPath(casePath)) { - // todo - what about modifications with path like case[id] or case[id]/xxx? - throw new UnsupportedOperationException("Campaign case can be modified only by specifying path=case; not via " + path); - //caseDelta.add(delta); - } - } - - modifications.removeAll(caseDelta); - - return caseDelta; - } - private boolean containsPhotoModification(Collection modifications) { ItemPath photoPath = new ItemPath(FocusType.F_JPEG_PHOTO); for (ItemDelta delta : modifications) { @@ -1949,18 +1530,6 @@ private void validateObjectType(PrismObject prismObjec } } - private void validateContainerable(C value, Class type) - throws SchemaException { - if (value == null) { - throw new SchemaException("Null object as a result of repository get operation for " + type); - } - Class realType = value.getClass(); - if (!type.isAssignableFrom(realType)) { - throw new SchemaException("Expected to find '" + type.getSimpleName() + "' but found '" + realType.getSimpleName()); - } - // TODO call check consistence if possible - } - private RObject createDataObjectFromJAXB(PrismObject prismObject, PrismIdentifierGenerator.Operation operation) throws SchemaException { @@ -2125,6 +1694,9 @@ public void testOrgClosureConsistency(boolean repairIfNecessary, OperationResult @PostConstruct public void initialize() { getClosureManager().initialize(this); + generalHelper = new GeneralHelper(getPrismContext()); + lookupTableHelper = new LookupTableHelper(getPrismContext(), generalHelper); + caseHelper = new CertificationCaseHelper(getPrismContext(), generalHelper); } /* (non-Javadoc) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 92a8b8f2081..290b7c7e9b7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -105,6 +105,7 @@ @NamedQuery(name = "delete.campaignCases", query = "delete RAccessCertificationCase c where c.ownerOid = :oid"), @NamedQuery(name = "delete.campaignCase", query = "delete RAccessCertificationCase c where c.ownerOid = :oid and c.id = :id"), @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), + @NamedQuery(name = "get.campaignCase", query = "select c.fullObject from RAccessCertificationCase c where c.ownerOid=:ownerOid and c.id=:id") }) @QueryEntity(anyElements = { @VirtualAny(jaxbNameLocalPart = "extension", ownerType = RObjectExtensionType.EXTENSION)}) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 5dd144e6c72..8bdabab02d6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.data.common.container; import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RObject; @@ -303,9 +304,10 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 rCase.setReviewRequestedTimestamp(case1.getReviewRequestedTimestamp()); rCase.setReviewDeadline(case1.getReviewDeadline()); rCase.setRemediedTimestamp(case1.getRemediedTimestamp()); + PrismContainerValue cvalue = case1.asPrismContainerValue(); String xml; try { - xml = prismContext.serializeContainerValueToString(case1.asPrismContainerValue(), new QName("value"), PrismContext.LANG_XML); + xml = prismContext.serializeContainerValueToString(cvalue, new QName("value"), PrismContext.LANG_XML); } catch (SchemaException e) { throw new IllegalStateException("Couldn't serialize certification case to string", e); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java new file mode 100644 index 00000000000..7c613cf312d --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; +import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; +import com.evolveum.midpoint.repo.sql.util.GetObjectResult; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.hibernate.Criteria; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.criterion.Restrictions; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Contains methods specific to handle certification cases. + * (As these cases are stored outside main certification campaign object.) + * + * It is quite a temporary solution in order to ease SqlRepositoryServiceImpl + * from tons of type-specific code. Serious solution would be to implement + * subobject-level operations more generically. + * + * @author mederly + */ +public class CertificationCaseHelper { + + private static final Trace LOGGER = TraceManager.getTrace(CertificationCaseHelper.class); + + private PrismContext prismContext; + private GeneralHelper generalHelper; + + public CertificationCaseHelper(PrismContext prismContext, GeneralHelper generalHelper) { + this.prismContext = prismContext; + this.generalHelper = generalHelper; + } + + public void addCertificationCampaignCases(Session session, RObject object, boolean merge) { + if (!(object instanceof RAccessCertificationCampaign)) { + return; + } + RAccessCertificationCampaign campaign = (RAccessCertificationCampaign) object; + + if (merge) { + deleteCertificationCampaignCases(session, campaign.getOid()); + } + if (campaign.getCases() != null) { + for (RAccessCertificationCase aCase : campaign.getCases()) { + session.save(aCase); + } + } + } + + public void addCertificationCampaignCases(Session session, String campaignOid, Collection values, int currentId) { + for (PrismContainerValue value : values) { + AccessCertificationCaseType caseType = new AccessCertificationCaseType(); + caseType.setupContainerValue(value); + caseType.setCampaignRef(ObjectTypeUtil.createObjectRef(campaignOid, ObjectTypes.ACCESS_CERTIFICATION_CAMPAIGN)); + RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, prismContext); + row.setId(currentId); + currentId++; + session.save(row); + } + } + + public void deleteCertificationCampaignCases(Session session, String oid) { + Query query = session.getNamedQuery("delete.campaignCases"); + query.setParameter("oid", oid); + + query.executeUpdate(); + } + + public Collection filterCampaignCaseModifications(Class type, + Collection modifications) { + Collection caseDelta = new ArrayList<>(); + if (!AccessCertificationCampaignType.class.equals(type)) { + return caseDelta; + } + + ItemPath casePath = new ItemPath(AccessCertificationCampaignType.F_CASE); + for (ItemDelta delta : modifications) { + ItemPath path = delta.getPath(); + if (path.isEmpty()) { + throw new UnsupportedOperationException("Certification campaign cannot be modified via empty-path modification"); + } else if (path.equivalent(casePath)) { + caseDelta.add(delta); + } else if (path.isSuperPath(casePath)) { // like case[id]/xxx +// throw new UnsupportedOperationException("Campaign case can be modified only by specifying path=case; not via " + path); + caseDelta.add(delta); + } + } + + modifications.removeAll(caseDelta); + + return caseDelta; + } + + public void updateCampaignCases(Session session, RObject object, + Collection modifications) throws SchemaException, ObjectNotFoundException { + if (modifications.isEmpty()) { + return; + } + + if (!(object instanceof RAccessCertificationCampaign)) { + throw new IllegalStateException("Object being modified is not a RAccessCertificationCampaign; it is " + object.getClass()); + } + final RAccessCertificationCampaign rCampaign = (RAccessCertificationCampaign) object; + final String campaignOid = object.getOid(); + + List casesAddedOrDeleted = addOrDeleteCases(session, campaignOid, modifications); + LOGGER.trace("Cases added/deleted (null means REPLACE operation) = {}", casesAddedOrDeleted); + + updateCasesContent(session, campaignOid, modifications, casesAddedOrDeleted); + } + + protected List addOrDeleteCases(Session session, String campaignOid, Collection modifications) throws SchemaException { + final ItemPath casePath = new ItemPath(AccessCertificationCampaignType.F_CASE); + boolean replacePresent = false; + List affectedIds = new ArrayList<>(); + for (ItemDelta delta : modifications) { + ItemPath deltaPath = delta.getPath(); + if (!casePath.isSubPathOrEquivalent(deltaPath)) { + throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + deltaPath); + } + + if (deltaPath.size() == 1) { + if (delta.getValuesToDelete() != null) { + // todo do 'bulk' delete like delete from ... where oid=? and id in (...) + for (PrismContainerValue value : (Collection) delta.getValuesToDelete()) { + Long id = value.getId(); + if (id == null) { + throw new SchemaException("Couldn't delete certification case with null id"); + } + affectedIds.add(id); + Query query = session.getNamedQuery("delete.campaignCase"); + query.setString("oid", campaignOid); + query.setInteger("id", RUtil.toInteger(id)); + query.executeUpdate(); + } + } + if (delta.getValuesToAdd() != null) { + int currentId = generalHelper.findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; + affectedIds.add((long) currentId); + addCertificationCampaignCases(session, campaignOid, delta.getValuesToAdd(), currentId); + } + if (delta.getValuesToReplace() != null) { + deleteCertificationCampaignCases(session, campaignOid); + addCertificationCampaignCases(session, campaignOid, delta.getValuesToReplace(), 1); + replacePresent = true; + } + + } + } + return replacePresent ? null : affectedIds; + } + + private void updateCasesContent(Session session, String campaignOid, Collection modifications, List casesAddedOrDeleted) throws SchemaException, ObjectNotFoundException { + for (ItemDelta delta : modifications) { + ItemPath deltaPath = delta.getPath(); + if (deltaPath.size() > 1) { + LOGGER.trace("Updating campaign " + campaignOid + " with delta " + delta); + + // should start with "case[id]" + long id = checkPathSanity(deltaPath, casesAddedOrDeleted); + + Query query = session.getNamedQuery("get.campaignCase"); + query.setString("ownerOid", campaignOid); + query.setInteger("id", (int) id); + + byte[] fullObject = (byte[]) query.uniqueResult(); + if (fullObject == null) { + throw new ObjectNotFoundException("Couldn't update cert campaign " + campaignOid + " + by delta with path " + deltaPath + " - specified case does not exist"); + } + AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(fullObject, prismContext); + + delta.setParentPath(delta.getParentPath().tail(2)); // remove "case[id]" from the delta path + delta.applyTo(aCase.asPrismContainerValue()); + RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(campaignOid, aCase, prismContext); + session.merge(rCase); + + LOGGER.trace("Access certification case " + rCase + " merged."); + } + } + } + + private long checkPathSanity(ItemPath deltaPath, List casesAddedOrDeleted) { + ItemPathSegment secondSegment = deltaPath.getSegments().get(1); + if (!(secondSegment instanceof IdItemPathSegment)) { + throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath + " - should start with case[id]"); + } + Long id = ((IdItemPathSegment) secondSegment).getId(); + if (id == null) { + throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath + " - should start with case[id]"); + } + if (deltaPath.size() == 2) { // not enough + throw new IllegalStateException("Couldn't update cert campaign by delta with path " + deltaPath + " - should start with case[id] and contain additional path"); + } + if (casesAddedOrDeleted == null || casesAddedOrDeleted.contains(id)) { + throw new IllegalArgumentException("Couldn't update certification case that was added/deleted in this operation. Path=" + deltaPath); + } + return id; + } + + + // TODO find a better name + public AccessCertificationCaseType updateLoadedCertificationCase(GetObjectResult result, + Collection> options, + Session session) throws SchemaException { + + AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), prismContext); + generalHelper.validateContainerable(aCase, AccessCertificationCaseType.class); + return aCase; + } + + // adds cases to campaign if requested by options + public void updateLoadedCampaign(PrismObject object, + Collection> options, + Session session) throws SchemaException { + if (!SelectorOptions.hasToLoadPath(AccessCertificationCampaignType.F_CASE, options)) { + return; + } + + LOGGER.debug("Loading certification campaign cases."); + + Criteria criteria = session.createCriteria(RAccessCertificationCase.class); + criteria.add(Restrictions.eq("ownerOid", object.getOid())); + + List cases = criteria.list(); + if (cases == null || cases.isEmpty()) { + return; + } + + AccessCertificationCampaignType campaign = (AccessCertificationCampaignType) object.asObjectable(); + List jaxbCases = campaign.getCase(); + for (RAccessCertificationCase rCase : cases) { + AccessCertificationCaseType jaxbCase = rCase.toJAXB(prismContext); + jaxbCases.add(jaxbCase); + } + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java new file mode 100644 index 00000000000..6bc25cb9f4b --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.util.exception.SchemaException; +import org.hibernate.Query; +import org.hibernate.Session; + +/** + * @author mederly + */ +public class GeneralHelper { + + private PrismContext prismContext; + + public GeneralHelper(PrismContext prismContext) { + this.prismContext = prismContext; + } + + public int findLastIdInRepo(Session session, String tableOid, String queryName) { + Query query = session.getNamedQuery(queryName); + query.setString("oid", tableOid); + Integer lastId = (Integer) query.uniqueResult(); + if (lastId == null) { + lastId = 0; + } + return lastId; + } + + public void validateContainerable(C value, Class type) + throws SchemaException { + if (value == null) { + throw new SchemaException("Null object as a result of repository get operation for " + type); + } + Class realType = value.getClass(); + if (!type.isAssignableFrom(realType)) { + throw new SchemaException("Expected to find '" + type.getSimpleName() + "' but found '" + realType.getSimpleName()); + } + // TODO call check consistence if possible + } + + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java new file mode 100644 index 00000000000..ae49c25e16c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.polystring.PrismDefaultPolyStringNormalizer; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.repo.sql.data.common.RLookupTable; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.ObjectSelector; +import com.evolveum.midpoint.schema.RelationalValueSearchQuery; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Criteria; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Restrictions; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Contains methods specific to handle LookupTable rows. + * (As these rows are stored outside main LookupTable object.) + * + * It is quite a temporary solution in order to ease SqlRepositoryServiceImpl + * from tons of type-specific code. Serious solution would be to implement + * subobject-level operations more generically. + * + * @author mederly + */ +public class LookupTableHelper { + + private static final Trace LOGGER = TraceManager.getTrace(LookupTableHelper.class); + + private PrismContext prismContext; + private GeneralHelper generalHelper; + + public LookupTableHelper(PrismContext prismContext, GeneralHelper generalHelper) { + this.prismContext = prismContext; + this.generalHelper = generalHelper; + } + + public void addLookupTableRows(Session session, RObject object, boolean merge) { + if (!(object instanceof RLookupTable)) { + return; + } + RLookupTable table = (RLookupTable) object; + + if (merge) { + deleteLookupTableRows(session, table.getOid()); + } + if (table.getRows() != null) { + for (RLookupTableRow row : table.getRows()) { + session.save(row); + } + } + } + + public void addLookupTableRows(Session session, String tableOid, Collection values, int currentId) { + for (PrismContainerValue value : values) { + LookupTableRowType rowType = new LookupTableRowType(); + rowType.setupContainerValue(value); + + RLookupTableRow row = RLookupTableRow.toRepo(tableOid, rowType); + row.setId(currentId); + currentId++; + session.save(row); + } + } + + /** + * This method removes all lookup table rows for object defined by oid + * @param session + * @param oid + */ + public void deleteLookupTableRows(Session session, String oid) { + Query query = session.getNamedQuery("delete.lookupTableData"); + query.setParameter("oid", oid); + + query.executeUpdate(); + } + + public void updateLookupTableData(Session session, RObject object, Collection modifications) { + if (modifications.isEmpty()) { + return; + } + + if (!(object instanceof RLookupTable)) { + throw new IllegalStateException("Object being modified is not a LookupTable; it is " + object.getClass()); + } + final RLookupTable rLookupTable = (RLookupTable) object; + final String tableOid = object.getOid(); + + for (ItemDelta delta : modifications) { + if (!(delta instanceof ContainerDelta) || delta.getPath().size() != 1) { + throw new IllegalStateException("Wrong table delta sneaked into updateLookupTableData: class=" + delta.getClass() + ", path=" + delta.getPath()); + } + // one "table" container modification + ContainerDelta containerDelta = (ContainerDelta) delta; + + if (containerDelta.getValuesToDelete() != null) { + // todo do 'bulk' delete like delete from ... where oid=? and id in (...) + for (PrismContainerValue value : (Collection) containerDelta.getValuesToDelete()) { + Query query = session.getNamedQuery("delete.lookupTableDataRow"); + query.setString("oid", tableOid); + query.setInteger("id", RUtil.toInteger(value.getId())); + query.executeUpdate(); + } + } + if (containerDelta.getValuesToAdd() != null) { + int currentId = generalHelper.findLastIdInRepo(session, tableOid, "get.lookupTableLastId") + 1; + addLookupTableRows(session, tableOid, containerDelta.getValuesToAdd(), currentId); + } + if (containerDelta.getValuesToReplace() != null) { + deleteLookupTableRows(session, tableOid); + addLookupTableRows(session, tableOid, containerDelta.getValuesToReplace(), 1); + } + } + } + + public GetOperationOptions findLookupTableGetOption(Collection> options) { + final ItemPath tablePath = new ItemPath(LookupTableType.F_ROW); + + Collection> filtered = SelectorOptions.filterRetrieveOptions(options); + for (SelectorOptions option : filtered) { + ObjectSelector selector = option.getSelector(); + if (selector == null) { + // Ignore this. These are top-level options. There will not + // apply to lookup table + continue; + } + ItemPath selected = selector.getPath(); + + if (tablePath.equivalent(selected)) { + return option.getOptions(); + } + } + + return null; + } + + public void updateLoadedLookupTable(PrismObject object, + Collection> options, + Session session) throws SchemaException { + if (!SelectorOptions.hasToLoadPath(LookupTableType.F_ROW, options)) { + return; + } + + LOGGER.debug("Loading lookup table data."); + + GetOperationOptions getOption = findLookupTableGetOption(options); + RelationalValueSearchQuery queryDef = getOption == null ? null : getOption.getRelationalValueSearchQuery(); + Criteria criteria = setupLookupTableRowsQuery(session, queryDef, object.getOid()); + if (queryDef != null && queryDef.getPaging() != null) { + ObjectPaging paging = queryDef.getPaging(); + + if (paging.getOffset() != null) { + criteria.setFirstResult(paging.getOffset()); + } + if (paging.getMaxSize() != null) { + criteria.setMaxResults(paging.getMaxSize()); + } + + ItemPath orderByPath = paging.getOrderBy(); + if (paging.getDirection() != null && orderByPath != null && !orderByPath.isEmpty()) { + if (orderByPath.size() > 1 || !(orderByPath.first() instanceof NameItemPathSegment)) { + throw new SchemaException("OrderBy has to consist of just one naming segment"); + } + String orderBy = ((NameItemPathSegment) (orderByPath.first())).getName().getLocalPart(); + switch (paging.getDirection()) { + case ASCENDING: + criteria.addOrder(Order.asc(orderBy)); + break; + case DESCENDING: + criteria.addOrder(Order.desc(orderBy)); + break; + } + } + } + + List rows = criteria.list(); + if (rows == null || rows.isEmpty()) { + return; + } + + LookupTableType lookup = (LookupTableType) object.asObjectable(); + List jaxbRows = lookup.getRow(); + for (RLookupTableRow row : rows) { + LookupTableRowType jaxbRow = row.toJAXB(); + jaxbRows.add(jaxbRow); + } + } + + private Criteria setupLookupTableRowsQuery(Session session, RelationalValueSearchQuery queryDef, String oid) { + Criteria criteria = session.createCriteria(RLookupTableRow.class); + criteria.add(Restrictions.eq("ownerOid", oid)); + + if (queryDef != null + && queryDef.getColumn() != null + && queryDef.getSearchType() != null + && StringUtils.isNotEmpty(queryDef.getSearchValue())) { + + String param = queryDef.getColumn().getLocalPart(); + String value = queryDef.getSearchValue(); + if (LookupTableRowType.F_LABEL.equals(queryDef.getColumn())) { + param = "label.norm"; + + PolyString poly = new PolyString(value); + poly.recompute(new PrismDefaultPolyStringNormalizer()); + value = poly.getNorm(); + } + switch (queryDef.getSearchType()) { + case EXACT: + criteria.add(Restrictions.eq(param, value)); + break; + case STARTS_WITH: + criteria.add(Restrictions.like(param, value + "%")); + break; + case SUBSTRING: + criteria.add(Restrictions.like(param, "%" + value + "%")); + } + } + + return criteria; + } + + public Collection filterLookupTableModifications(Class type, + Collection modifications) { + Collection tableDelta = new ArrayList<>(); + if (!LookupTableType.class.equals(type)) { + return tableDelta; + } + + ItemPath tablePath = new ItemPath(LookupTableType.F_ROW); + for (ItemDelta delta : modifications) { + ItemPath path = delta.getPath(); + if (path.isEmpty()) { + throw new UnsupportedOperationException("Lookup table cannot be modified via empty-path modification"); + } else if (path.equivalent(tablePath)) { + tableDelta.add(delta); + } else if (path.isSuperPath(tablePath)) { + // todo - what about modifications with path like table[id] or table[id]/xxx where xxx=key|value|label? + throw new UnsupportedOperationException("Lookup table row can be modified only by specifying path=table"); + } + } + + modifications.removeAll(tableDelta); + + return tableDelta; + } +} From 699d774629f0726a120ee00695c5fe5586339255 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 26 Nov 2015 12:57:41 +0100 Subject: [PATCH 019/116] Added resolveNames option for certification cases. GUI is almost usable (without sorting). --- .../api/CertificationManager.java | 6 +- .../impl/AccCertQueryHelper.java | 13 ++- .../repo/sql/SqlRepositoryServiceImpl.java | 79 ++----------- .../container/RAccessCertificationCase.java | 40 ++++--- .../embedded/REmbeddedNamedReference.java | 4 + .../sql/helpers/CertificationCaseHelper.java | 15 ++- .../repo/sql/helpers/GeneralHelper.java | 9 +- .../repo/sql/helpers/LookupTableHelper.java | 12 +- .../sql/helpers/NameResolutionHelper.java | 104 ++++++++++++++++++ .../repo/sql/query2/QueryInterpreter2.java | 5 +- .../main/resources/ctx-repository-session.xml | 8 +- 11 files changed, 182 insertions(+), 113 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/NameResolutionHelper.java diff --git a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java index 82866f0dc66..622b69caeaf 100644 --- a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java +++ b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java @@ -162,7 +162,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * Query argument for cases is the same as in the searchCases call. * Contrary to searchCases, this method allows to collect cases for more than one campaign * (e.g. to present a reviewer all of his/her cases). - * So, instead of campaignOid there is a campaignQuery allowing to select one, more, and even all campaigns. + * So, instead of campaignOid it will be (when implemented) possible to specify conditions for the campaign in the caseQuery. * * Contrary to all the other methods, cases returned from this method have campaignRef set - both reference and the campaign object itself. * (THIS MAY CHANGE IN THE FUTURE.) @@ -178,13 +178,15 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * @param notDecidedOnly If true, only response==(NO_DECISION or null) should be returned. * It is currently not possible to formulate this using Query API * (we don't know the ID of the decision element to refer to). + * + * NOT IMPLEMENTED NOW. + * * @param options Options to use (currently supported is RESOLVE_NAMES). * @param task Task in context of which all operations will take place. * @param parentResult Result for the operations. * @return A list of relevant certification cases. * */ - List searchDecisions(ObjectQuery caseQuery, String reviewerOid, boolean notDecidedOnly, Collection> options, diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java index 0ba0fc66223..061d7327422 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.model.api.ModelService; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.*; @@ -90,6 +91,8 @@ protected List searchCases(String campaignOid, Obje protected List searchDecisions(ObjectQuery query, String reviewerOid, boolean notDecidedOnly, Collection> options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException { + // TODO FILTER BY NOT_DECIDED_ONLY + // enhance filter with reviewerRef + enabled ObjectQuery newQuery; ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); @@ -139,12 +142,10 @@ protected List searchDecisions(ObjectQuery query, S } } -// if (!notDecidedOnly || !isDecided(_case)) { -// ObjectReferenceType campaignRef = ObjectTypeUtil.createObjectRef(campaignObject); -// campaignRef.asReferenceValue().setObject(campaignObject); -// _case.setCampaignRef(campaignRef); -// caseList.add(_case); -// } + PrismObject campaignObject = campaign.asPrismObject(); + ObjectReferenceType campaignRef = ObjectTypeUtil.createObjectRef(campaignObject); + _case.setCampaignRef(campaignRef); + _case.getCampaignRef().asReferenceValue().setObject(campaignObject); // has to be done AFTER setCampaignRef in order to preserve the value! } return caseList; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 3731f9fb558..a54f617c59d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -30,9 +30,6 @@ import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.Visitable; -import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; @@ -50,11 +47,11 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.data.common.any.RValueType; -import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.helpers.CertificationCaseHelper; import com.evolveum.midpoint.repo.sql.helpers.LookupTableHelper; import com.evolveum.midpoint.repo.sql.helpers.GeneralHelper; +import com.evolveum.midpoint.repo.sql.helpers.NameResolutionHelper; import com.evolveum.midpoint.repo.sql.query.QueryEngine; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.RQuery; @@ -107,7 +104,7 @@ import org.hibernate.exception.ConstraintViolationException; import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.jdbc.Work; -import org.hibernate.transform.Transformers; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import javax.annotation.PostConstruct; @@ -123,10 +120,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Properties; @@ -151,11 +146,18 @@ public class SqlRepositoryServiceImpl extends SqlBaseService implements Reposito private static final String DETAILS_HIBERNATE_DIALECT = "hibernateDialect"; private static final String DETAILS_HIBERNATE_HBM_2_DDL = "hibernateHbm2ddl"; - // initialized in post-construct method + @Autowired private GeneralHelper generalHelper; + + @Autowired private LookupTableHelper lookupTableHelper; + + @Autowired private CertificationCaseHelper caseHelper; + @Autowired + private NameResolutionHelper nameResolutionHelper; + private OrgClosureManager closureManager; public SqlRepositoryServiceImpl(SqlRepositoryFactory repositoryFactory) { @@ -1103,69 +1105,13 @@ private PrismObject updateLoadedObject(GetObjectResult caseHelper.updateLoadedCampaign(prismObject, options, session); } - GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); - - if (GetOperationOptions.isResolveNames(rootOptions)) { - final List oidsToResolve = new ArrayList(); - Visitor oidExtractor = new Visitor() { - @Override - public void visit(Visitable visitable) { - if (visitable instanceof PrismReferenceValue) { - PrismReferenceValue value = (PrismReferenceValue) visitable; - if (value.getTargetName() != null) { // just for sure - return; - } - if (value.getObject() != null) { // improbable but possible - value.setTargetName(value.getObject().getName()); - return; - } - if (value.getOid() == null) { // shouldn't occur as well - return; - } - oidsToResolve.add(value.getOid()); - } - } - }; - prismObject.accept(oidExtractor); - - if (!oidsToResolve.isEmpty()) { - Query query = session.getNamedQuery("resolveReferences"); - query.setParameterList("oid", oidsToResolve); - query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); - - List> results = query.list(); - final Map oidNameMap = consolidateResults(results); - - Visitor nameSetter = new Visitor() { - @Override - public void visit(Visitable visitable) { - if (visitable instanceof PrismReferenceValue) { - PrismReferenceValue value = (PrismReferenceValue) visitable; - if (value.getTargetName() == null && value.getOid() != null) { - value.setTargetName(oidNameMap.get(value.getOid())); - } - } - } - }; - prismObject.accept(nameSetter); - } - } - + nameResolutionHelper.resolveNamesIfRequested(session, prismObject.getValue(), options); validateObjectType(prismObject, type); return prismObject; } - private Map consolidateResults(List> results){ - Map oidNameMap = new HashMap(); - for (Map map : results){ - PolyStringType name = RPolyString.copyToJAXB((RPolyString) map.get("1")); - oidNameMap.put((String)map.get("0"), new PolyString(name.getOrig(), name.getNorm())); - } - return oidNameMap; - } - private void applyShadowAttributeDefinitions(Class anyValueType, PrismObject object, Session session) throws SchemaException { @@ -1694,9 +1640,6 @@ public void testOrgClosureConsistency(boolean repairIfNecessary, OperationResult @PostConstruct public void initialize() { getClosureManager().initialize(this); - generalHelper = new GeneralHelper(getPrismContext()); - lookupTableHelper = new LookupTableHelper(getPrismContext(), generalHelper); - caseHelper = new CertificationCaseHelper(getPrismContext(), generalHelper); } /* (non-Javadoc) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 8bdabab02d6..d1eef42d771 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -21,27 +21,34 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RObject; -import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedNamedReference; +import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; -import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; -import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.Validate; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Where; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.Index; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Transient; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import java.util.Arrays; @@ -75,8 +82,8 @@ public class RAccessCertificationCase implements Container { private Integer id; private Set reviewerRef; - private REmbeddedNamedReference objectRef; - private REmbeddedNamedReference targetRef; + private REmbeddedReference objectRef; + private REmbeddedReference targetRef; private boolean enabled; private XMLGregorianCalendar reviewRequestedTimestamp; @@ -136,15 +143,16 @@ public void setReviewerRef(Set reviewerRef) { } @Embedded - public REmbeddedNamedReference getTargetRef() { + public REmbeddedReference getTargetRef() { return targetRef; } @Embedded - public REmbeddedNamedReference getObjectRef() { + public REmbeddedReference getObjectRef() { return objectRef; } + @Column(name = "case_enabled") public boolean isEnabled() { return enabled; } @@ -173,11 +181,11 @@ public void setId(Integer id) { this.id = id; } - public void setTargetRef(REmbeddedNamedReference targetRef) { + public void setTargetRef(REmbeddedReference targetRef) { this.targetRef = targetRef; } - public void setObjectRef(REmbeddedNamedReference objectRef) { + public void setObjectRef(REmbeddedReference objectRef) { this.objectRef = objectRef; } @@ -296,8 +304,8 @@ public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificati private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, PrismContext prismContext) { RAccessCertificationCase rCase = new RAccessCertificationCase(); rCase.setId(RUtil.toInteger(case1.getId())); - rCase.setObjectRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getObjectRef(), prismContext)); - rCase.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(case1.getTargetRef(), prismContext)); + rCase.setObjectRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getObjectRef(), prismContext)); + rCase.setTargetRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getTargetRef(), prismContext)); rCase.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( case1.getReviewerRef(), prismContext, rCase, RCReferenceOwner.CASE_REVIEWER)); rCase.setEnabled(case1.isEnabled()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java index ef4ac6412cc..18cad099028 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedNamedReference.java @@ -33,6 +33,10 @@ import javax.persistence.Enumerated; /** + * Reference containing the name of referenced object. + * Originally thought to be used in certifications, but replaced by dynamically joining RObject table. + * So keeping this for possible future use only. + * * @author mederly */ @Embeddable diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 7c613cf312d..7d01a2e58ed 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -43,6 +43,8 @@ import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Restrictions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; @@ -58,17 +60,19 @@ * * @author mederly */ +@Component public class CertificationCaseHelper { private static final Trace LOGGER = TraceManager.getTrace(CertificationCaseHelper.class); + @Autowired private PrismContext prismContext; + + @Autowired private GeneralHelper generalHelper; - public CertificationCaseHelper(PrismContext prismContext, GeneralHelper generalHelper) { - this.prismContext = prismContext; - this.generalHelper = generalHelper; - } + @Autowired + private NameResolutionHelper nameResolutionHelper; public void addCertificationCampaignCases(Session session, RObject object, boolean merge) { if (!(object instanceof RAccessCertificationCampaign)) { @@ -120,7 +124,6 @@ public Collection filterCampaignCase } else if (path.equivalent(casePath)) { caseDelta.add(delta); } else if (path.isSuperPath(casePath)) { // like case[id]/xxx -// throw new UnsupportedOperationException("Campaign case can be modified only by specifying path=case; not via " + path); caseDelta.add(delta); } } @@ -243,6 +246,7 @@ public AccessCertificationCaseType updateLoadedCertificationCase(GetObjectResult Session session) throws SchemaException { AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), prismContext); + nameResolutionHelper.resolveNamesIfRequested(session, aCase.asPrismContainerValue(), options); generalHelper.validateContainerable(aCase, AccessCertificationCaseType.class); return aCase; } @@ -260,6 +264,7 @@ public void updateLoadedCampaign(PrismObject object, Criteria criteria = session.createCriteria(RAccessCertificationCase.class); criteria.add(Restrictions.eq("ownerOid", object.getOid())); + // TODO fetch only XML representation List cases = criteria.list(); if (cases == null || cases.isEmpty()) { return; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java index 6bc25cb9f4b..2335da1df50 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/GeneralHelper.java @@ -21,18 +21,15 @@ import com.evolveum.midpoint.util.exception.SchemaException; import org.hibernate.Query; import org.hibernate.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; /** * @author mederly */ +@Component public class GeneralHelper { - private PrismContext prismContext; - - public GeneralHelper(PrismContext prismContext) { - this.prismContext = prismContext; - } - public int findLastIdInRepo(Session session, String tableOid, String queryName) { Query query = session.getNamedQuery(queryName); query.setString("oid", tableOid); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java index ae49c25e16c..8be7f41fe6d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java @@ -46,6 +46,8 @@ import org.hibernate.Session; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; @@ -59,20 +61,16 @@ * from tons of type-specific code. Serious solution would be to implement * subobject-level operations more generically. * - * @author mederly + * @author lazyman, mederly */ +@Component public class LookupTableHelper { private static final Trace LOGGER = TraceManager.getTrace(LookupTableHelper.class); - private PrismContext prismContext; + @Autowired private GeneralHelper generalHelper; - public LookupTableHelper(PrismContext prismContext, GeneralHelper generalHelper) { - this.prismContext = prismContext; - this.generalHelper = generalHelper; - } - public void addLookupTableRows(Session session, RObject object, boolean merge) { if (!(object instanceof RLookupTable)) { return; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/NameResolutionHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/NameResolutionHelper.java new file mode 100644 index 00000000000..82593fdc1f8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/NameResolutionHelper.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.transform.Transformers; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author lazyman, katkav, mederly + */ +@Component +public class NameResolutionHelper { + + // TODO keep names between invocations (e.g. when called from searchObjects/searchContainers) + public void resolveNamesIfRequested(Session session, PrismContainerValue containerValue, Collection> options) { + GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); + if (GetOperationOptions.isResolveNames(rootOptions)) { + final List oidsToResolve = new ArrayList<>(); + Visitor oidExtractor = new Visitor() { + @Override + public void visit(Visitable visitable) { + if (visitable instanceof PrismReferenceValue) { + PrismReferenceValue value = (PrismReferenceValue) visitable; + if (value.getTargetName() != null) { // just for sure + return; + } + if (value.getObject() != null) { // improbable but possible + value.setTargetName(value.getObject().getName()); + return; + } + if (value.getOid() == null) { // shouldn't occur as well + return; + } + oidsToResolve.add(value.getOid()); + } + } + }; + containerValue.accept(oidExtractor); + + if (!oidsToResolve.isEmpty()) { + Query query = session.getNamedQuery("resolveReferences"); + query.setParameterList("oid", oidsToResolve); + query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); + + List> results = query.list(); + final Map oidNameMap = consolidateResults(results); + + Visitor nameSetter = new Visitor() { + @Override + public void visit(Visitable visitable) { + if (visitable instanceof PrismReferenceValue) { + PrismReferenceValue value = (PrismReferenceValue) visitable; + if (value.getTargetName() == null && value.getOid() != null) { + value.setTargetName(oidNameMap.get(value.getOid())); + } + } + } + }; + containerValue.accept(nameSetter); + } + } + } + + private Map consolidateResults(List> results){ + Map oidNameMap = new HashMap(); + for (Map map : results){ + PolyStringType name = RPolyString.copyToJAXB((RPolyString) map.get("1")); + oidNameMap.put((String)map.get("0"), new PolyString(name.getOrig(), name.getNorm())); + } + return oidNameMap; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 0bd168088c9..7cb7c80f7c3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -327,12 +327,13 @@ public void updatePagingAndSorting(RootHibernateQuery return; } // FIXME this has to be enhanced for multi-segment paths! (e.g. create joins if needed) - Definition def = registry.findDefinition(type, paging.getOrderBy(), Definition.class).getItemDefinition(); - if (def == null) { + DefinitionSearchResult result = registry.findDefinition(type, paging.getOrderBy(), Definition.class); + if (result == null) { LOGGER.warn("Unknown path '" + paging.getOrderBy() + "', couldn't find definition for it, " + "list will not be ordered by it."); return; } + Definition def = result.getItemDefinition(); String propertyName = hibernateQuery.getPrimaryEntityAlias() + "." + def.getJpaName(); if (PolyString.class.equals(def.getJaxbType())) { diff --git a/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml b/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml index 0919aaf7865..27d1843a69b 100644 --- a/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml +++ b/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml @@ -17,8 +17,11 @@ + + + \ No newline at end of file From 8fefe765c81d7888078cd0900b181a02d44805ae Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 27 Nov 2015 08:49:17 +0100 Subject: [PATCH 020/116] Support for multi-named orderBy paths. Preliminary hibernate support for target references in repo queries. --- .../main/resources/ctx-repository-session.xml | 9 ++- .../repo/sql/QueryInterpreter2Test.java | 70 ++++++++++++++----- .../repo/sql/data/common/RObject.java | 2 + .../sql/data/common/RObjectReference.java | 19 +++++ .../container/RAssignmentReference.java | 13 ++++ .../common/container/RCertCaseReference.java | 14 ++++ .../common/container/RContainerReference.java | 11 +++ .../common/embedded/REmbeddedReference.java | 31 +++++++- .../sql/query2/InterpretationContext.java | 4 ++ .../repo/sql/query2/QueryInterpreter2.java | 53 ++++++++------ .../repo/sql/util/MidPointNamingStrategy.java | 30 ++++++-- 11 files changed, 211 insertions(+), 45 deletions(-) diff --git a/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml b/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml index 618e513de6b..5fbcb1b4313 100644 --- a/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml +++ b/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml @@ -17,8 +17,11 @@ + + + + \ No newline at end of file diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 87dcdd7e53a..76eab93fa89 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -16,7 +16,6 @@ package com.evolveum.midpoint.repo.sql; -import com.evolveum.midpoint.common.filter.Filter; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContainerDefinition; @@ -352,7 +351,7 @@ public void test021QueryTwoOrganizationsStrictOr() throws Exception { " ( o2.orig = :orig2 and o2.norm = :norm2 ) )"; // NOTE: this could be implemented more efficiently by using only one join... or the query itself can be formulated - // via In filter (when available) or ForValue filter (also, when available) + // via In filter (when available) or Exists filter (also, when available) String real = getInterpretedQuery2(session, UserType.class, query); assertEqualsIgnoreWhitespace(expected, real); @@ -413,7 +412,7 @@ public void test030QueryTaskDependent() throws Exception { } } - @Test(enabled = false, expectedExceptions = QueryException.class) + @Test(expectedExceptions = QueryException.class) public void test040QueryClob() throws Exception { Session session = open(); @@ -637,7 +636,21 @@ public void test080QueryExistsAssignment() throws Exception { query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, OrderDirection.ASCENDING)); String real = getInterpretedQuery2(session, UserType.class, query); - //assertEqualsIgnoreWhitespace(expected, real); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "where\n" + + " a.activation.administrativeStatus = :administrativeStatus\n" + + "order by u.name.orig asc\n"; + assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); } @@ -1842,19 +1855,6 @@ public void test560queryMetadataTimestamp() throws Exception { public void test570queryObjectypeByTypeUserAndLocality() throws Exception { Session session = open(); try { -// Criteria main = session.createCriteria(RObject.class, "o"); -// ProjectionList projections = Projections.projectionList(); -// addFullObjectProjectionList("o", projections, false); -// main.setProjection(projections); -// -// Conjunction c = Restrictions.conjunction(); -// main.add(c); -// c.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.USER)); -// c.add(Restrictions.and(Restrictions.eq("o.localityUser.orig", "Caribbean"), -// Restrictions.eq("o.localityUser.norm", "caribbean"))); -// -// String expected = HibernateToSqlTranslator.toSql(main); - EqualFilter eq = EqualFilter.createEqual(new ItemPath(UserType.F_LOCALITY), UserType.class, prismContext, new PolyString("Caribbean", "caribbean")); TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE, eq); @@ -2485,6 +2485,42 @@ public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Excep } } + @Test + public void test800OrderBySingleton() throws Exception { + Session session = open(); + + try { + /* + * ### UserType: order by activation/administrativeStatus + */ + + ObjectQuery query = ObjectQuery.createObjectQuery( + null, + ObjectPaging.createPaging( + new ItemPath(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), + OrderDirection.ASCENDING)); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "order by u.activation.administrativeStatus asc"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + // TODO negative tests - order by entity, reference, any, collection + // TODO implement checks for "order by" for non-singletons + // TODO search for "no decision" condition (V2) // TODO sorting based on referenced entity names (V2) // TODO for cases: sorting based on object name, target name, campaign name (!) (V2-3) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 290b7c7e9b7..04e53280d93 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -53,6 +53,8 @@ import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.NamedQueries; import org.hibernate.annotations.NamedQuery; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import org.hibernate.annotations.Where; import javax.persistence.Column; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java index afc50f27c79..7d777e118fc 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java @@ -28,6 +28,8 @@ import org.apache.commons.lang.Validate; import org.hibernate.annotations.ForeignKey; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.*; @@ -51,11 +53,14 @@ public class RObjectReference implements ObjectReference { //owner private RObject owner; private String ownerOid; + //other primary key fields private String targetOid; private String relation; private RObjectType type; + private RObject target; + public RObjectReference() { } @@ -77,6 +82,16 @@ public String getOwnerOid() { return ownerOid; } + //@MapsId("target") + @ForeignKey(name="none") + @ManyToOne(fetch = FetchType.LAZY, optional = true) + @JoinColumn(referencedColumnName = "oid", updatable = false, insertable = false, nullable = true) + @NotFound(action = NotFoundAction.IGNORE) + @NotQueryable + public RObject getTarget() { + return target; + } + @Id @Column(name = "targetOid", length = RUtil.COLUMN_LENGTH_OID) @Override @@ -126,6 +141,10 @@ public void setRelation(String relation) { this.relation = relation; } + public void setTarget(RObject target) { // shouldn't be called + this.target = target; + } + public void setTargetOid(String targetOid) { this.targetOid = targetOid; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java index ff2a0b9e480..c2474522520 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignmentReference.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.data.common.container; +import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.RCObjectReferenceId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; @@ -25,6 +26,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import org.hibernate.annotations.ForeignKey; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.*; @@ -64,6 +67,16 @@ public Integer getOwnerId() { return super.getOwnerId(); } + //@MapsId("target") + @ForeignKey(name="none") + @ManyToOne(fetch = FetchType.LAZY, optional = true) + @JoinColumn(referencedColumnName = "oid", updatable = false, insertable = false, nullable = true) + @NotFound(action = NotFoundAction.IGNORE) + @NotQueryable + public RObject getTarget() { + return super.getTarget(); + } + @Id @Column(name = "targetOid", length = RUtil.COLUMN_LENGTH_OID) @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java index d1b6ea00117..a817fda339a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.data.common.container; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.RCObjectReferenceId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; @@ -26,6 +27,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import org.apache.commons.lang.Validate; import org.hibernate.annotations.ForeignKey; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.Column; import javax.persistence.Entity; @@ -34,6 +37,7 @@ import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.IdClass; +import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MapsId; import javax.persistence.Table; @@ -87,6 +91,16 @@ public Integer getOwnerId() { return super.getOwnerId(); } + //@MapsId("target") + @ForeignKey(name="none") + @ManyToOne(fetch = FetchType.LAZY, optional = true) + @JoinColumn(referencedColumnName = "oid", updatable = false, insertable = false, nullable = true) + @NotFound(action = NotFoundAction.IGNORE) + @NotQueryable + public RObject getTarget() { + return super.getTarget(); + } + @Id @Column(name = "targetOid", length = RUtil.COLUMN_LENGTH_OID) @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java index 8768ed326ff..76f42684252 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; @@ -53,6 +54,8 @@ public abstract class RContainerReference implements ObjectReference { private String relation; private RObjectType type; + private RObject target; + public RContainerReference() { } @@ -75,6 +78,10 @@ protected Integer getOwnerId() { return ownerId; } + public RObject getTarget() { + return target; + } + @Override public String getTargetOid() { return targetOid; @@ -108,6 +115,10 @@ public void setRelation(String relation) { this.relation = relation; } + public void setTarget(RObject target) { // shouldn't be called + this.target = target; + } + public void setTargetOid(String targetOid) { this.targetOid = targetOid; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java index fe1f8d7d9b9..659a7134571 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java @@ -18,7 +18,9 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; +import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; @@ -28,11 +30,19 @@ import org.apache.commons.lang.Validate; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; +import org.hibernate.annotations.ForeignKey; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.EnumType; import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; /** * @author lazyman @@ -41,6 +51,8 @@ public class REmbeddedReference implements ObjectReference { //target + @NotFound(action = NotFoundAction.IGNORE) + private RObject target; private String targetOid; //other fields private RObjectType type; @@ -53,9 +65,22 @@ public String getRelation() { return relation; } - @Column(length = RUtil.COLUMN_LENGTH_OID, insertable = true, updatable = true, nullable = true) + //@MapsId("target") + @ForeignKey(name="none") + @ManyToOne(fetch = FetchType.LAZY, optional = true) + @JoinColumn(referencedColumnName = "oid", updatable = false, insertable = false, nullable = true) + @NotFound(action = NotFoundAction.IGNORE) + @NotQueryable + public RObject getTarget() { + return target; + } + + @Column(length = RUtil.COLUMN_LENGTH_OID, insertable = true, updatable = true, nullable = true /*, insertable = false, updatable = false */) @Override public String getTargetOid() { + if (target != null && targetOid == null) { + targetOid = target.getOid(); + } return targetOid; } @@ -77,6 +102,10 @@ public void setType(RObjectType type) { this.type = type; } + public void setTarget(RObject target) { + this.target = target; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index 8a5d1ae88ef..f310bb3ccc8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -124,4 +124,8 @@ public EntityDefinition getRootEntityDefinition() { public boolean isObject() { return ObjectType.class.isAssignableFrom(type); } + + public String getPrimaryEntityAlias() { + return hibernateQuery.getPrimaryEntityAlias(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 7cb7c80f7c3..add9f609d6a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -289,7 +289,7 @@ private void interpretPagingAndSorting(InterpretationContext context, ObjectQuer if (query.getPaging() instanceof ObjectPagingAfterOid) { updatePagingAndSortingByOid(hibernateQuery, (ObjectPagingAfterOid) query.getPaging()); // very special case - ascending ordering by OID (nothing more) } else { - updatePagingAndSorting(hibernateQuery, context.getType(), query.getPaging()); + updatePagingAndSorting(context, hibernateQuery, query.getPaging()); } } } @@ -305,7 +305,7 @@ protected void updatePagingAndSortingByOid(RootHibernateQuery hibernateQuery, Ob } } - public void updatePagingAndSorting(RootHibernateQuery hibernateQuery, Class type, ObjectPaging paging) throws QueryException { + public void updatePagingAndSorting(InterpretationContext context, RootHibernateQuery hibernateQuery, ObjectPaging paging) throws QueryException { if (paging == null) { return; } @@ -316,41 +316,50 @@ public void updatePagingAndSorting(RootHibernateQuery hibernateQuery.setMaxResults(paging.getMaxSize()); } - if (paging.getDirection() == null && (paging.getOrderBy() == null || paging.getOrderBy().isEmpty())) { - return; + ItemPath orderByPath = paging.getOrderBy(); + if (ItemPath.isNullOrEmpty(orderByPath)) { + if (paging.getDirection() == null) { + return; + } else { + throw new QueryException("Ordering by empty property path is not possible"); + } } - QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - if (paging.getOrderBy() == null || paging.getOrderBy().isEmpty() || paging.getOrderBy().size() > 1 || !(paging.getOrderBy().first() instanceof NameItemPathSegment)) { - LOGGER.warn("Ordering by property path with size not equal 1 is not supported '" + paging.getOrderBy() - + "'."); - return; - } - // FIXME this has to be enhanced for multi-segment paths! (e.g. create joins if needed) - DefinitionSearchResult result = registry.findDefinition(type, paging.getOrderBy(), Definition.class); + ProperDefinitionSearchResult result = context.getHelper().findProperDefinition( + context.getRootEntityDefinition(), orderByPath, Definition.class); if (result == null) { - LOGGER.warn("Unknown path '" + paging.getOrderBy() + "', couldn't find definition for it, " + throw new QueryException("Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it."); - return; + } else if (result.getItemDefinition() instanceof AnyDefinition) { + throw new QueryException("Sorting based on extension item or attribute is not supported yet: " + orderByPath); + } else if (result.getItemDefinition() instanceof ReferenceDefinition) { + throw new QueryException("Sorting based on reference is not supported: " + orderByPath); + } else if (result.getItemDefinition().isCollection()) { + throw new QueryException("Sorting based on multi-valued item is not supported: " + orderByPath); + } else if (result.getItemDefinition() instanceof EntityDefinition) { + throw new QueryException("Sorting based on entity is not supported: " + orderByPath); + } else if (!(result.getItemDefinition() instanceof PropertyDefinition)) { + throw new IllegalStateException("Unknown item definition type: " + result.getClass()); } - Definition def = result.getItemDefinition(); - String propertyName = hibernateQuery.getPrimaryEntityAlias() + "." + def.getJpaName(); - if (PolyString.class.equals(def.getJaxbType())) { - propertyName += ".orig"; + EntityDefinition baseEntityDefinition = result.getEntityDefinition(); + PropertyDefinition orderByDefinition = (PropertyDefinition) result.getItemDefinition(); + String hqlPropertyPath = context.getHelper().prepareJoins(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition) + + "." + orderByDefinition.getJpaName(); + if (PolyString.class.equals(orderByDefinition.getJaxbType())) { + hqlPropertyPath += ".orig"; } - if (paging.getDirection() != null) { switch (paging.getDirection()) { case ASCENDING: - hibernateQuery.setOrder(propertyName, OrderDirection.ASCENDING); + hibernateQuery.setOrder(hqlPropertyPath, OrderDirection.ASCENDING); break; case DESCENDING: - hibernateQuery.setOrder(propertyName, OrderDirection.DESCENDING); + hibernateQuery.setOrder(hqlPropertyPath, OrderDirection.DESCENDING); break; } } else { - hibernateQuery.setOrder(propertyName, OrderDirection.ASCENDING); + hibernateQuery.setOrder(hqlPropertyPath, OrderDirection.ASCENDING); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/MidPointNamingStrategy.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/MidPointNamingStrategy.java index 3c589c0d8b5..b5b133403c6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/MidPointNamingStrategy.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/MidPointNamingStrategy.java @@ -42,7 +42,7 @@ public String classToTableName(String className) { String result = "m_" + name.toLowerCase(); result = fixLength(result); - LOGGER.trace("classToTableName {} to {}", new Object[]{className, result}); + LOGGER.trace("classToTableName {} to {}", className, result); return result; } @@ -61,7 +61,7 @@ public String logicalColumnName(String columnName, String propertyName) { } result = fixLength(result); - LOGGER.trace("logicalColumnName {} {} to {}", new Object[]{columnName, propertyName, result}); + LOGGER.trace("logicalColumnName {} {} to {}", columnName, propertyName, result); return result; } @@ -76,8 +76,30 @@ public String propertyToColumnName(String propertyName) { } result = fixLength(result); - LOGGER.trace("propertyToColumnName {} to {} (original: {})", - new Object[]{propertyName, result, super.propertyToColumnName(propertyName)}); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("propertyToColumnName {} to {} (original: {})", + propertyName, result, super.propertyToColumnName(propertyName)); + } + return result; + } + + @Override + public String foreignKeyColumnName(String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName) { + String header = propertyName != null ? propertyName.replaceAll("\\.", "_") : propertyTableName; + String result; + if (header.endsWith("target") && referencedColumnName.equals("oid")) { + result = header + "Oid"; // to keep compatibility with existing mappings + } else { + result = header + "_" + referencedColumnName; + } + result = fixLength(result); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("foreignKeyColumnName for propertyName={}, propertyEntityName={}, propertyTableName={}, " + + "referencedColumnName={} returns {} (original: {})", propertyName, propertyEntityName, + propertyTableName, referencedColumnName, result, + super.foreignKeyColumnName(propertyName, propertyEntityName, propertyTableName, referencedColumnName)); + } return result; } From e9d7a23ef7f8e13bab5006b03e284b4a9bc72017 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 27 Nov 2015 16:33:02 +0100 Subject: [PATCH 021/116] Preliminary support for ".." and "@" in filter paths. --- .../midpoint/prism/ComplexTypeDefinition.java | 49 ++++++++--- .../midpoint/prism/PrismConstants.java | 5 +- .../prism/PrismContainerDefinition.java | 39 +++++++-- .../prism/PrismReferenceDefinition.java | 16 +++- .../midpoint/prism/delta/ItemDelta.java | 2 + .../midpoint/prism/path/ItemPath.java | 86 +++++++++++++------ .../path/ObjectReferencePathSegment.java | 40 +++++++++ .../prism/path/ParentPathSegment.java | 40 +++++++++ .../prism/path/ReferencePathSegment.java | 26 ++++++ .../midpoint/prism/schema/SchemaRegistry.java | 23 ++++- .../impl/controller/ModelController.java | 1 + 11 files changed, 274 insertions(+), 53 deletions(-) create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ObjectReferencePathSegment.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ParentPathSegment.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/ComplexTypeDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/ComplexTypeDefinition.java index 491c46d96f4..a861e020024 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/ComplexTypeDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/ComplexTypeDefinition.java @@ -16,8 +16,13 @@ package com.evolveum.midpoint.prism; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; +import com.evolveum.midpoint.prism.path.ParentPathSegment; +import com.evolveum.midpoint.prism.path.ReferencePathSegment; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.PrettyPrinter; @@ -163,14 +168,14 @@ public PrismPropertyDefinition createPropertyDefinifion(QName name) { public PrismPropertyDefinition createPropertyDefinition(String localName, QName typeName) { QName name = new QName(getSchemaNamespace(),localName); - return createPropertyDefinifion(name,typeName); + return createPropertyDefinifion(name, typeName); } public PrismPropertyDefinition createPropertyDefinifion(String localName, String localTypeName) { QName name = new QName(getSchemaNamespace(),localName); QName typeName = new QName(getSchemaNamespace(),localTypeName); - return createPropertyDefinifion(name,typeName); + return createPropertyDefinifion(name, typeName); } /** @@ -222,21 +227,37 @@ public ID findItemDefinition(ItemPath path) { } public ID findItemDefinition(ItemPath path, Class clazz) { - while (!path.isEmpty() && !(path.first() instanceof NameItemPathSegment)) { - path = path.rest(); - } - if (path.isEmpty()) { - throw new IllegalArgumentException("Cannot resolve empty path on complex type definition "+this); - } - QName firstName = ((NameItemPathSegment)path.first()).getName(); - for (ItemDefinition def : getDefinitions()) { + for (;;) { + if (path.isEmpty()) { + throw new IllegalArgumentException("Cannot resolve empty path on complex type definition "+this); + } + ItemPathSegment first = path.first(); + if (first instanceof NameItemPathSegment) { + QName firstName = ((NameItemPathSegment)first).getName(); + return findNamedItemDefinition(firstName, path.rest(), clazz); + } else if (first instanceof IdItemPathSegment) { + path = path.rest(); + } else if (first instanceof ParentPathSegment) { + ComplexTypeDefinition parent = getSchemaRegistry().determineParentDefinition(this, path.rest()); + return parent.findItemDefinition(path.rest(), clazz); + } else if (first instanceof ObjectReferencePathSegment) { + throw new IllegalStateException("Couldn't use '@' path segment in this context. CTD=" + getTypeName() + ", path=" + path); + } else { + throw new IllegalStateException("Unexpected path segment: " + first + " in " + path); + } + } + } + + // path starts with NamedItemPathSegment + private ID findNamedItemDefinition(QName firstName, ItemPath rest, Class clazz) { + for (ItemDefinition def : getDefinitions()) { if (firstName != null && firstName.equals(def.getName())) { - return (ID) def.findItemDefinition(path.rest(), clazz); + return (ID) def.findItemDefinition(rest, clazz); } } - return null; - } - + return null; + } + private boolean isItemValid(ItemDefinition def, QName name, Class clazz, boolean caseInsensitive) { if (def == null) { return false; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java index 965c13d0c9f..69008729574 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java @@ -92,7 +92,10 @@ public class PrismConstants { public static final QName Q_ORDER_BY = new QName(NS_QUERY, "orderBy"); public static final QName Q_ANY = new QName(NS_QUERY, "any"); - + // Path constants + public static final QName T_PARENT = new QName(NS_TYPES, "parent"); + public static final QName T_OBJECT_REFERENCE = new QName(NS_TYPES, "objectReference"); + // Misc public static final Class DEFAULT_VALUE_CLASS = String.class; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java index 4396731fc73..308a5c23560 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java @@ -18,8 +18,12 @@ import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; +import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.prism.schema.PrismSchema; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.DebugDumpable; @@ -208,16 +212,33 @@ private D findRuntimeItemDefinition(QName firstName, } public ID findItemDefinition(ItemPath path, Class clazz) { - while (!path.isEmpty() && !(path.first() instanceof NameItemPathSegment)) { - path = path.rest(); - } - if (path.isEmpty()) { - return (ID) this; + for (;;) { + if (path.isEmpty()) { + if (clazz.isAssignableFrom(PrismContainerDefinition.class)) { + return (ID) this; + } else { + return null; + } + } + ItemPathSegment first = path.first(); + if (first instanceof NameItemPathSegment) { + QName firstName = ((NameItemPathSegment)first).getName(); + return findNamedItemDefinition(firstName, path.rest(), clazz); + } else if (first instanceof IdItemPathSegment) { + path = path.rest(); + } else if (first instanceof ParentPathSegment) { + ComplexTypeDefinition parent = getSchemaRegistry().determineParentDefinition(getComplexTypeDefinition(), path.rest()); + return parent.findItemDefinition(path.tail(), clazz); + } else if (first instanceof ObjectReferencePathSegment) { + throw new IllegalStateException("Couldn't use '@' path segment in this context. PCD=" + getTypeName() + ", path=" + path); + } else { + throw new IllegalStateException("Unexpected path segment: " + first + " in " + path); + } } - - QName firstName = ((NameItemPathSegment)path.first()).getName(); - ItemPath rest = path.rest(); - + } + + public ID findNamedItemDefinition(QName firstName, ItemPath rest, Class clazz) { + // we need to be compatible with older versions..soo if the path does // not contains qnames with namespaces defined (but the prefix was // specified) match definition according to the local name diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceDefinition.java index 0d1ff7a1399..f0bf92d34c8 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceDefinition.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; import com.evolveum.midpoint.util.QNameUtil; @@ -103,8 +104,19 @@ public boolean isValidFor(QName elementQName, Class cl } return false; } - - @Override + + @Override + T findItemDefinition(ItemPath path, Class clazz) { + if (path.isEmpty() || !(path.first() instanceof ObjectReferencePathSegment)) { + return super.findItemDefinition(path, clazz); + } else { + ItemPath rest = path.rest(); + PrismObjectDefinition referencedObjectDefinition = getSchemaRegistry().determineReferencedObjectDefinition(targetTypeName, rest); + return (T) referencedObjectDefinition.findItemDefinition(rest, clazz); + } + } + + @Override public PrismReference instantiate() { return instantiate(getName()); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java index df9315640da..48008330c57 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java @@ -82,6 +82,7 @@ protected ItemDelta(QName elementName, D itemDefinition, PrismContext prismConte protected ItemDelta(ItemPath parentPath, QName elementName, D itemDefinition, PrismContext prismContext) { //checkPrismContext(prismContext, itemDefinition); + ItemPath.checkNoReferences(parentPath); this.prismContext = prismContext; this.elementName = elementName; this.parentPath = parentPath; @@ -90,6 +91,7 @@ protected ItemDelta(ItemPath parentPath, QName elementName, D itemDefinition, Pr protected ItemDelta(ItemPath path, D itemDefinition, PrismContext prismContext) { //checkPrismContext(prismContext, itemDefinition); + ItemPath.checkNoReferences(path); this.prismContext = prismContext; if (path == null) { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index a700a265d8d..9eccef24eab 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -15,19 +15,19 @@ */ package com.evolveum.midpoint.prism.path; +import com.evolveum.midpoint.prism.PrismConstants; +import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; /** * @author semancik @@ -54,22 +54,32 @@ public ItemPath() { } public ItemPath(QName... qnames) { - this.segments = new ArrayList(qnames.length); + this.segments = new ArrayList<>(qnames.length); for (QName qname : qnames) { add(qname); } } public ItemPath(String... names) { - this.segments = new ArrayList(names.length); + this.segments = new ArrayList<>(names.length); for (String name : names) { - add(new QName(name)); + add(stringToQName(name)); } } + private QName stringToQName(String name) { + Validate.notNull(name, "name"); + if ("..".equals(name)) { + return PrismConstants.T_PARENT; + } else if ("@".equals(name)) { + return PrismConstants.T_OBJECT_REFERENCE; + } else { + return new QName(name); + } + } - public ItemPath(ItemPath parentPath, QName subName) { - this.segments = new ArrayList(parentPath.segments.size()+1); + public ItemPath(ItemPath parentPath, QName subName) { + this.segments = new ArrayList<>(parentPath.segments.size()+1); segments.addAll(parentPath.segments); add(subName); } @@ -82,31 +92,29 @@ public ItemPath(ItemPath parentPath, ItemPath childPath) { public ItemPath(List segments) { - this.segments = new ArrayList(segments.size()); + this.segments = new ArrayList<>(segments.size()); this.segments.addAll(segments); } public ItemPath(List segments, ItemPathSegment subSegment) { - this.segments = new ArrayList(segments.size()+1); + this.segments = new ArrayList<>(segments.size()+1); this.segments.addAll(segments); this.segments.add(subSegment); } public ItemPath(List segments, QName subName) { - this.segments = new ArrayList(segments.size()+1); + this.segments = new ArrayList<>(segments.size()+1); this.segments.addAll(segments); add(subName); } public ItemPath(ItemPathSegment... segments) { - this.segments = new ArrayList(segments.length); - for (ItemPathSegment seg : segments) { - this.segments.add(seg); - } + this.segments = new ArrayList<>(segments.length); + Collections.addAll(this.segments, segments); } public ItemPath(ItemPath parentPath, ItemPathSegment subSegment) { - this.segments = new ArrayList(parentPath.segments.size()+1); + this.segments = new ArrayList<>(parentPath.segments.size() + 1); this.segments.addAll(parentPath.segments); this.segments.add(subSegment); } @@ -139,7 +147,13 @@ public static ItemPath subPath(ItemPath prefix, ItemPathSegment subSegment) { } private void add(QName qname) { - this.segments.add(new NameItemPathSegment(qname)); + if (qname.equals(PrismConstants.T_PARENT)) { + this.segments.add(new ParentPathSegment()); + } else if (qname.equals(PrismConstants.T_OBJECT_REFERENCE)) { + this.segments.add(new ObjectReferencePathSegment()); + } else { + this.segments.add(new NameItemPathSegment(qname)); + } } public List getSegments() { @@ -154,10 +168,7 @@ public ItemPathSegment first() { } public ItemPath rest() { - if (segments.size() == 0) { - return EMPTY_PATH; - } - return new ItemPath(segments.subList(1, segments.size())); + return tail(); } public NameItemPathSegment lastNamed() { @@ -341,6 +352,14 @@ public static boolean containsSingleNameSegment(ItemPath path) { return path != null && path.size() == 1 && path.first() instanceof NameItemPathSegment; } + public boolean startsWith(Class clazz) { + if (isEmpty()) { + return false; + } else { + return clazz.isAssignableFrom(first().getClass()); + } + } + public enum CompareResult { EQUIVALENT, SUPERPATH, @@ -542,4 +561,23 @@ public ItemPath clone() { return clone; } + public static boolean containsReferences(ItemPath path) { + return path != null && path.containsReferences(); + } + + public boolean containsReferences() { + for (ItemPathSegment segment : segments) { + if (segment instanceof ReferencePathSegment) { + return true; + } + } + return false; + } + + public static void checkNoReferences(ItemPath path) { + if (containsReferences(path)) { + throw new IllegalStateException("Item path shouldn't contain references but it does: " + path); + } + } + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ObjectReferencePathSegment.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ObjectReferencePathSegment.java new file mode 100644 index 00000000000..573f2e7f881 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ObjectReferencePathSegment.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.path; + +/** + * Denotes referenced object, like "assignment/targetRef/@/name" (name of assignment's target object) + * + * @author mederly + */ +public class ObjectReferencePathSegment extends ReferencePathSegment { + + @Override + public boolean equivalent(Object obj) { + return equals(obj); + } + + @Override + public ItemPathSegment clone() { + return new ObjectReferencePathSegment(); + } + + @Override + public String toString() { + return "@"; + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ParentPathSegment.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ParentPathSegment.java new file mode 100644 index 00000000000..642ebdecf2f --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ParentPathSegment.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.path; + +/** + * Denotes parent object or container. + * + * @author mederly + */ +public class ParentPathSegment extends ReferencePathSegment { + + @Override + public boolean equivalent(Object obj) { + return equals(obj); + } + + @Override + public ItemPathSegment clone() { + return new ParentPathSegment(); + } + + @Override + public String toString() { + return ".."; + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java new file mode 100644 index 00000000000..c3049e865a9 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.path; + +/** + * Denotes reference path segment: either ".." meaning owner, or "@" meaning referenced object. + * (Note that these are to be used only in filters, for now.) + * + * @author mederly + */ +public abstract class ReferencePathSegment extends ItemPathSegment { +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java index 896edc52849..f50071720b0 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java @@ -520,9 +520,9 @@ public LSInput resolveResource(String type, String namespaceURI, String publicId // Prefer built-in resolution over the pre-parsed one. This is less efficient, but if the order is swapped // the parsers complaints about re-definition of the elements // InputSource inputSource = resolveResourceUsingBuiltinResolver(type,namespaceURI,publicId,systemId,baseURI); - InputSource inputSource = resolveResourceFromRegisteredSchemas(type,namespaceURI,publicId,systemId,baseURI); + InputSource inputSource = resolveResourceFromRegisteredSchemas(type, namespaceURI, publicId, systemId, baseURI); if (inputSource == null) { - inputSource = resolveResourceUsingBuiltinResolver(type,namespaceURI,publicId,systemId,baseURI); + inputSource = resolveResourceUsingBuiltinResolver(type, namespaceURI, publicId, systemId, baseURI); // inputSource = resolveResourceFromRegisteredSchemas(type,namespaceURI,publicId,systemId,baseURI); } if (inputSource == null) { @@ -620,7 +620,24 @@ public QName qualifyTypeName(QName typeName) throws SchemaException { return resolveUnqualifiedTypeName(typeName); } - class Input implements LSInput { + public ComplexTypeDefinition determineParentDefinition(ComplexTypeDefinition complexTypeDefinition, ItemPath rest) { + ComplexTypeDefinition def = findComplexTypeDefinition(new QName("ObjectType")); // FIXME BRUTAL HACK + if (def == null) { + throw new IllegalStateException("Couldn't find definition for parent for " + complexTypeDefinition.getTypeName() + ", path=" + rest); + } + return def; + } + + public PrismObjectDefinition determineReferencedObjectDefinition(QName targetTypeName, ItemPath rest) { + // TEMPORARY HACK -- TODO FIXME + PrismObjectDefinition def = findObjectDefinitionByType(targetTypeName); + if (def == null) { + throw new IllegalStateException("Couldn't find definition for referenced object for " + targetTypeName + ", path=" + rest); + } + return def; + } + + class Input implements LSInput { private String publicId; private String systemId; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java index 8a8e687d79e..bf715621cac 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java @@ -386,6 +386,7 @@ private void resolve(PrismObject object, SelectorOptions return; } ItemPath path = selector.getPath(); + ItemPath.checkNoReferences(path); resolve(object, path, option, task, result); } From dec0db4ad9fffa8aa90569aaee019dd49c149a92 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 28 Nov 2015 01:33:34 +0100 Subject: [PATCH 022/116] Big refactoring of JPA registry in order to implement object references resolution, not quite finished yet. --- .../repo/sql/QueryInterpreter2Test.java | 24 ++ .../repo/sql/data/common/RAbstractRole.java | 6 +- .../midpoint/repo/sql/data/common/RFocus.java | 12 +- .../repo/sql/data/common/RObject.java | 20 +- .../sql/data/common/RObjectReference.java | 10 +- .../repo/sql/data/common/RObjectTemplate.java | 6 +- .../repo/sql/data/common/RResource.java | 8 +- .../definition/ClassDefinitionParser.java | 9 +- .../sql/query2/DefinitionSearchResult.java | 5 +- .../sql/query2/InterpretationContext.java | 23 +- .../repo/sql/query2/InterpreterHelper.java | 106 ++++---- .../query2/ProperDefinitionSearchResult.java | 20 +- .../sql/query2/QueryDefinitionRegistry2.java | 92 ++++--- .../repo/sql/query2/QueryInterpreter2.java | 89 +++---- .../definition/ClassDefinitionParser.java | 247 ++++++++---------- .../definition/CollectionSpecification.java | 11 +- .../sql/query2/definition/Definition.java | 220 ---------------- .../definition/DefinitionComparator.java | 16 +- .../sql/query2/definition/DefinitionPath.java | 34 +-- ...yDefinition.java => JpaAnyDefinition.java} | 17 +- .../sql/query2/definition/JpaDefinition.java | 170 ++++++++++++ ...n.java => JpaEntityContentDefinition.java} | 144 +++++----- .../definition/JpaEntityDefinition.java | 37 +++ .../definition/JpaEntityItemDefinition.java | 93 +++++++ .../query2/definition/JpaItemDefinition.java | 86 ++++++ .../sql/query2/definition/JpaNamePath.java | 53 ---- ...nition.java => JpaPropertyDefinition.java} | 18 +- .../definition/JpaReferenceDefinition.java | 92 +++++++ .../definition/JpaRootEntityDefinition.java | 77 ++++++ .../query2/definition/PathTranslation.java | 45 ---- .../definition/ReferenceDefinition.java | 58 ---- .../definition/VirtualAnyDefinition.java | 15 +- .../VirtualCollectionSpecification.java | 23 +- .../definition/VirtualEntityDefinition.java | 53 ---- .../definition/VirtualPropertyDefinition.java | 53 ---- .../repo/sql/query2/hqm/HibernateQuery.java | 58 ++-- .../sql/query2/hqm/RootHibernateQuery.java | 5 +- .../hqm/condition/HibernateSubquery.java | 4 +- .../query2/restriction/AndRestriction.java | 6 +- .../restriction/AnyPropertyRestriction.java | 22 +- .../query2/restriction/ExistsRestriction.java | 10 +- .../query2/restriction/InOidRestriction.java | 12 +- .../query2/restriction/ItemRestriction.java | 5 +- .../restriction/ItemValueRestriction.java | 22 +- .../restriction/LogicalRestriction.java | 4 +- .../restriction/NaryLogicalRestriction.java | 5 +- .../query2/restriction/NotRestriction.java | 7 +- .../sql/query2/restriction/OrRestriction.java | 4 +- .../query2/restriction/OrgRestriction.java | 4 +- .../restriction/PropertyRestriction.java | 24 +- .../restriction/ReferenceRestriction.java | 18 +- .../sql/query2/restriction/Restriction.java | 12 +- .../query2/restriction/TypeRestriction.java | 5 +- .../restriction/UnaryLogicalRestriction.java | 5 +- 54 files changed, 1161 insertions(+), 1063 deletions(-) delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{AnyDefinition.java => JpaAnyDefinition.java} (72%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{EntityDefinition.java => JpaEntityContentDefinition.java} (53%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{PropertyDefinition.java => JpaPropertyDefinition.java} (76%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 76eab93fa89..05ded6ce90e 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; @@ -2485,6 +2486,28 @@ public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Excep } } + @Test + public void test750DereferenceLink() throws Exception { + Session session = open(); + + try { + /* + * ### UserType: link/name contains 'test.com' + */ + + ObjectFilter filter = SubstringFilter.createSubstring( + new ItemPath(UserType.F_LINK_REF, PrismConstants.T_OBJECT_REFERENCE, ShadowType.F_NAME), + UserType.class, prismContext, "test.com"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String real = getInterpretedQuery2(session, UserType.class, query); +// assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test public void test800OrderBySingleton() throws Exception { Session session = open(); @@ -2518,6 +2541,7 @@ public void test800OrderBySingleton() throws Exception { } } + // TODO negative tests - order by entity, reference, any, collection // TODO implement checks for "order by" for non-singletons diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java index 7b97f00ed9b..8a010bc8de1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java @@ -62,7 +62,7 @@ public abstract class RAbstractRole extends RFocus exclusion; private Boolean requestable; - private Set approverRef; + private Set> approverRef; private String approvalProcess; public Boolean getRequestable() { @@ -93,14 +93,14 @@ public Set getExclusion() { @OneToMany(mappedBy = "owner", orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getApproverRef() { + public Set> getApproverRef() { if (approverRef == null) { approverRef = new HashSet<>(); } return approverRef; } - public void setApproverRef(Set approverRef) { + public void setApproverRef(Set> approverRef) { this.approverRef = approverRef; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java index fec48cbf379..cc9a290ef15 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RFocus.java @@ -56,8 +56,8 @@ @Index(name = "iFocusEffective", columnNames = "effectiveStatus")}) public abstract class RFocus extends RObject { - private Set linkRef; - private Set roleMembershipRef; + private Set> linkRef; + private Set> roleMembershipRef; private Set assignments; private RActivation activation; //photo @@ -68,7 +68,7 @@ public abstract class RFocus extends RObject { @OneToMany(mappedBy = "owner", orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getLinkRef() { + public Set> getLinkRef() { if (linkRef == null) { linkRef = new HashSet<>(); } @@ -79,7 +79,7 @@ public Set getLinkRef() { @OneToMany(mappedBy = "owner", orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getRoleMembershipRef() { + public Set> getRoleMembershipRef() { if (roleMembershipRef == null) { roleMembershipRef = new HashSet<>(); } @@ -130,11 +130,11 @@ public void setAssignments(Set assignments) { this.assignments = assignments; } - public void setLinkRef(Set linkRef) { + public void setLinkRef(Set> linkRef) { this.linkRef = linkRef; } - public void setRoleMembershipRef(Set roleMembershipRef) { + public void setRoleMembershipRef(Set> roleMembershipRef) { this.roleMembershipRef = roleMembershipRef; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 04e53280d93..a5fd56b44c8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -118,7 +118,7 @@ @Index(name = "iObjectTypeClass", columnList = "objectTypeClass"), @Index(name = "iObjectCreateTimestamp", columnList = "createTimestamp")}) @Inheritance(strategy = InheritanceType.JOINED) -public abstract class RObject implements Metadata, EntityState, Serializable { +public abstract class RObject implements Metadata>, EntityState, Serializable { public static final String F_OBJECT_TYPE_CLASS = "objectTypeClass"; @@ -135,17 +135,17 @@ public abstract class RObject implements Metadata parentOrgRef; + private Set> parentOrgRef; private Set trigger; private REmbeddedReference tenantRef; //Metadata private XMLGregorianCalendar createTimestamp; private REmbeddedReference creatorRef; - private Set createApproverRef; + private Set> createApproverRef; private String createChannel; private XMLGregorianCalendar modifyTimestamp; private REmbeddedReference modifierRef; - private Set modifyApproverRef; + private Set> modifyApproverRef; private String modifyChannel; //extension, and other "any" like shadow/attributes private Short booleansCount; @@ -188,7 +188,7 @@ public Set getTrigger() { @Where(clause = RObjectReference.REFERENCE_TYPE + "= 0") @OneToMany(mappedBy = RObjectReference.F_OWNER, orphanRemoval = true) @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getParentOrgRef() { + public Set> getParentOrgRef() { if (parentOrgRef == null) { parentOrgRef = new HashSet<>(); } @@ -229,7 +229,7 @@ public byte[] getFullObject() { @OneToMany(mappedBy = RObjectReference.F_OWNER, orphanRemoval = true) // @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getCreateApproverRef() { + public Set> getCreateApproverRef() { if (createApproverRef == null) { createApproverRef = new HashSet<>(); } @@ -258,7 +258,7 @@ public REmbeddedReference getModifierRef() { @OneToMany(mappedBy = RObjectReference.F_OWNER, orphanRemoval = true) // @JoinTable(foreignKey = @ForeignKey(name = "none")) @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getModifyApproverRef() { + public Set> getModifyApproverRef() { if (modifyApproverRef == null) { modifyApproverRef = new HashSet<>(); } @@ -401,7 +401,7 @@ public void setObjectTypeClass(RObjectType objectTypeClass) { this.objectTypeClass = objectTypeClass; } - public void setCreateApproverRef(Set createApproverRef) { + public void setCreateApproverRef(Set> createApproverRef) { this.createApproverRef = createApproverRef; } @@ -421,7 +421,7 @@ public void setModifierRef(REmbeddedReference modifierRef) { this.modifierRef = modifierRef; } - public void setModifyApproverRef(Set modifyApproverRef) { + public void setModifyApproverRef(Set> modifyApproverRef) { this.modifyApproverRef = modifyApproverRef; } @@ -465,7 +465,7 @@ public void setAncestors(Set ancestors) { this.ancestors = ancestors; } - public void setParentOrgRef(Set parentOrgRef) { + public void setParentOrgRef(Set> parentOrgRef) { this.parentOrgRef = parentOrgRef; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java index 7d777e118fc..6bc20e2ef65 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectReference.java @@ -42,7 +42,7 @@ @Table(name = "m_reference", indexes = { @javax.persistence.Index(name = "iReferenceTargetOid", columnList = "targetOid") }) -public class RObjectReference implements ObjectReference { +public class RObjectReference implements ObjectReference { public static final String REFERENCE_TYPE = "reference_type"; @@ -59,7 +59,7 @@ public class RObjectReference implements ObjectReference { private String relation; private RObjectType type; - private RObject target; + private T target; public RObjectReference() { } @@ -84,11 +84,11 @@ public String getOwnerOid() { //@MapsId("target") @ForeignKey(name="none") - @ManyToOne(fetch = FetchType.LAZY, optional = true) + @ManyToOne(fetch = FetchType.LAZY, optional = true, targetEntity = RObject.class) @JoinColumn(referencedColumnName = "oid", updatable = false, insertable = false, nullable = true) @NotFound(action = NotFoundAction.IGNORE) @NotQueryable - public RObject getTarget() { + public T getTarget() { return target; } @@ -141,7 +141,7 @@ public void setRelation(String relation) { this.relation = relation; } - public void setTarget(RObject target) { // shouldn't be called + public void setTarget(T target) { // shouldn't be called this.target = target; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectTemplate.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectTemplate.java index ee7abeb2487..1ca8ab3d6b9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectTemplate.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObjectTemplate.java @@ -45,13 +45,13 @@ public class RObjectTemplate extends RObject { private RPolyString name; private RObjectTemplateType type; - private Set includeRef; + private Set> includeRef; @Where(clause = RObjectReference.REFERENCE_TYPE + "= 7") @OneToMany(mappedBy = RObjectReference.F_OWNER, orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getIncludeRef() { + public Set> getIncludeRef() { if (includeRef == null) { includeRef = new HashSet<>(); } @@ -72,7 +72,7 @@ public RPolyString getName() { return name; } - public void setIncludeRef(Set includeRef) { + public void setIncludeRef(Set> includeRef) { this.includeRef = includeRef; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RResource.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RResource.java index a81cace0d06..8bf994b58ab 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RResource.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RResource.java @@ -55,7 +55,7 @@ public class RResource extends RObject { //resource business configuration, embedded component can't be used, because then it couldn't use //non embedded approverRef relationship private RResourceAdministrativeState administrativeState; - private Set approverRef; + private Set> approverRef; //end of resource business configuration @Enumerated(EnumType.ORDINAL) @@ -68,9 +68,9 @@ public RResourceAdministrativeState getAdministrativeState() { @OneToMany(mappedBy = "owner", orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getApproverRef() { + public Set> getApproverRef() { if (approverRef == null) { - approverRef = new HashSet(); + approverRef = new HashSet<>(); } return approverRef; } @@ -94,7 +94,7 @@ public void setAdministrativeState(RResourceAdministrativeState administrativeSt this.administrativeState = administrativeState; } - public void setApproverRef(Set approverRef) { + public void setApproverRef(Set> approverRef) { this.approverRef = approverRef; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/ClassDefinitionParser.java index 9dce70371b5..1bdde704c2c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/ClassDefinitionParser.java @@ -34,6 +34,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.Set; /** @@ -159,7 +160,13 @@ private CollectionDefinition updateCollectionDefinition(CollectionDefinition def if (object instanceof Method) { Method method = (Method) object; ParameterizedType type = (ParameterizedType) method.getGenericReturnType(); - Class clazz = (Class) type.getActualTypeArguments()[0]; + Type type1 = type.getActualTypeArguments()[0]; + Class clazz; + if (type1 instanceof Class) { + clazz = ((Class) type1); + } else { + clazz = (Class) ((ParameterizedType) type1).getRawType(); + } QName realJaxbName = getJaxbName(method); Class jaxbType = getJaxbType(clazz); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java index d9361211401..48a2cf273b8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java @@ -17,14 +17,13 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; import org.apache.commons.lang.Validate; /** * @author mederly */ -public class DefinitionSearchResult { +public class DefinitionSearchResult { private T itemDefinition; // definition of the item itself private ItemPath remainder; // what has remained unresolved of the original search path diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index f310bb3ccc8..cb2852d0542 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -18,32 +18,15 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; -import com.evolveum.midpoint.repo.sql.query2.restriction.TypeRestriction; -import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.apache.commons.lang.Validate; import org.hibernate.Session; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - /** * @author lazyman * @author mederly @@ -67,7 +50,7 @@ public class InterpretationContext { * by the search operation, or the one that was refined from abstract types (ObjectType, AbstractRoleType, ...) * in the process of restriction construction. */ - private EntityDefinition rootEntityDefinition; + private JpaRootEntityDefinition rootEntityDefinition; public InterpretationContext(QueryInterpreter2 interpreter, Class type, PrismContext prismContext, Session session) throws QueryException { @@ -117,7 +100,7 @@ public InterpreterHelper getHelper() { return helper; } - public EntityDefinition getRootEntityDefinition() { + public JpaRootEntityDefinition getRootEntityDefinition() { return rootEntityDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java index f9f41e27264..e24c11b32fd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java @@ -21,15 +21,15 @@ import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; -import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionSpecification; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.DefinitionPath; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionSpecification; -import com.evolveum.midpoint.repo.sql.query2.hqm.EntityReference; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; @@ -61,7 +61,7 @@ public InterpreterHelper(InterpretationContext interpretationContext) { } // returns property path that can be used to access the item values - public String prepareJoins(ItemPath relativePath, String currentHqlPath, EntityDefinition baseEntityDefinition) throws QueryException { + public String prepareJoins(ItemPath relativePath, String currentHqlPath, JpaEntityDefinition baseEntityDefinition) throws QueryException { LOGGER.trace("Updating query context based on path {}", relativePath); @@ -74,46 +74,53 @@ public String prepareJoins(ItemPath relativePath, String currentHqlPath, EntityD * * Or more complex: * - assignment.modifyApproverRef -> "left join u.assignments a (...) left join a.modifyApproverRef m (...)" - * - assignment.target.longs -> "left join u.assignments a (...), RObject o left join o.longs (...)" + * - assignment.target.longs -> "left join u.assignments a (...) left join a.target t left join t.longs (...)" */ - DefinitionPath definitionPath = baseEntityDefinition.translatePath(relativePath); - - List definitions = definitionPath.getDefinitions(); - for (int i = 0; i < definitions.size(); i++) { - Definition definition = definitions.get(i); - if (definition instanceof EntityDefinition) { - EntityDefinition entityDef = (EntityDefinition) definition; - if (!entityDef.isEmbedded() || entityDef.isCollection()) { - LOGGER.trace("Adding join for '{}' to context", entityDef.getJpaName()); + + JpaDefinition currentDefinition = (JpaDefinition) baseEntityDefinition; + ItemPath itemPathRemainder = relativePath; + while (!ItemPath.isNullOrEmpty(itemPathRemainder)) { + + DefinitionSearchResult result = currentDefinition.nextDefinition(itemPathRemainder); + LOGGER.trace("nextDefinition on {} returned {}", itemPathRemainder, result != null ? result.getItemDefinition() : "(null)"); + if (result == null) { // sorry we failed (however, this should be caught before -> so IllegalStateException) + throw new IllegalStateException("Couldn't find " + itemPathRemainder + " in " + currentDefinition); + } + JpaItemDefinition itemDefinition = result.getItemDefinition(); + + if (itemDefinition instanceof JpaAnyDefinition) { + JpaAnyDefinition anyDefinition = (JpaAnyDefinition) itemDefinition; + if (anyDefinition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes + LOGGER.trace("Adding join for '{}' to context", anyDefinition); + currentHqlPath = addJoin(anyDefinition, currentHqlPath); + } + break; // we're done + } else if (itemDefinition instanceof JpaEntityItemDefinition) { + JpaEntityItemDefinition entityDef = (JpaEntityItemDefinition) itemDefinition; + if (!entityDef.isEmbedded() || entityDef.isMultivalued()) { + LOGGER.trace("Adding join for '{}' to context", entityDef); currentHqlPath = addJoin(entityDef, currentHqlPath); } else { currentHqlPath += "." + entityDef.getJpaName(); } - } else if (definition instanceof AnyDefinition) { - if (definition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes - LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); - currentHqlPath = addJoin(definition, currentHqlPath); - } - break; - } else if (definition instanceof PropertyDefinition || definition instanceof ReferenceDefinition) { - if (definition.isCollection()) { - LOGGER.trace("Adding join for '{}' to context", definition.getJpaName()); - currentHqlPath = addJoin(definition, currentHqlPath); + } else if (itemDefinition instanceof JpaPropertyDefinition || itemDefinition instanceof JpaReferenceDefinition) { + if (itemDefinition.isMultivalued()) { + LOGGER.trace("Adding join for '{}' to context", itemDefinition); + currentHqlPath = addJoin(itemDefinition, currentHqlPath); } - break; // quite redundant, as this is the last item in the chain } else { - throw new QueryException("Not implemented yet: " + definition); + throw new QueryException("Not implemented yet: " + itemDefinition); } - // TODO entity crossjoin references (when crossing object boundaries) + itemPathRemainder = result.getRemainder(); + currentDefinition = itemDefinition; } LOGGER.trace("prepareJoins({}) returning currentHqlPath of {}", relativePath, currentHqlPath); return currentHqlPath; } - protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) throws QueryException { + private String addJoin(JpaItemDefinition joinedItemDefinition, String currentHqlPath) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) String joinedItemJpaName = joinedItemDefinition.getJpaName(); String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); @@ -133,7 +140,7 @@ protected String addJoin(Definition joinedItemDefinition, String currentHqlPath) condition = conditions.iterator().next(); } } - entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); + hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); return joinedItemAlias; } @@ -166,10 +173,9 @@ private Object createQueryParamValue(VirtualQueryParam param) throws QueryExcept public String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - EntityReference entityReference = hibernateQuery.getPrimaryEntity(); // TODO other references (in the future) String joinedItemJpaName = anyAssociationName; String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName); + String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); AndCondition conjunction = hibernateQuery.createAnd(); if (ownerType != null) { // null for assignment extensions @@ -177,7 +183,7 @@ public String addJoinAny(String currentHqlPath, String anyAssociationName, QName } conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); - entityReference.addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); + hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); return joinedItemAlias; } @@ -190,13 +196,13 @@ public String addJoinAny(String currentHqlPath, String anyAssociationName, QName * @param clazz Kind of definition to be looked for * @return Entity type definition + item definition, or null if nothing was found */ - public ProperDefinitionSearchResult findProperDefinition(EntityDefinition baseEntityDefinition, - ItemPath path, Class clazz) - throws QueryException { + public + ProperDefinitionSearchResult findProperDefinition(JpaEntityDefinition baseEntityDefinition, + ItemPath path, Class clazz) throws QueryException { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); ProperDefinitionSearchResult candidateResult = null; - for (EntityDefinition entityDefinition : findPossibleBaseEntities(baseEntityDefinition, registry)) { + for (JpaEntityDefinition entityDefinition : findPossibleBaseEntities(baseEntityDefinition, registry)) { DefinitionSearchResult result = entityDefinition.findDefinition(path, clazz); if (result != null) { if (candidateResult == null) { @@ -206,19 +212,19 @@ public ProperDefinitionSearchResult findProperDefiniti // there is no possibility of false alarm. if (!candidateResult.getEntityDefinition().isAssignableFrom(entityDefinition)) { throw new QueryException("Unable to determine root entity for " + path + ": found incompatible candidates: " + - candidateResult.getEntityDefinition().getJpaName() + " and " + - entityDefinition.getJpaName()); + candidateResult.getEntityDefinition() + " and " + + entityDefinition); } } } } LOGGER.trace("findProperDefinition: base={}, path={}, class={} -- returning {}", - baseEntityDefinition.getShortInfo(), path, clazz.getSimpleName(), candidateResult); + baseEntityDefinition, path, clazz.getSimpleName(), candidateResult); return candidateResult; } - private List findPossibleBaseEntities(EntityDefinition entityDefinition, QueryDefinitionRegistry2 registry) { - List retval = new ArrayList<>(); + private List findPossibleBaseEntities(JpaEntityDefinition entityDefinition, QueryDefinitionRegistry2 registry) { + List retval = new ArrayList<>(); retval.add(entityDefinition); // (possibly) abstract one has to go first if (entityDefinition.isAbstract()) { // just for efficiency retval.addAll(registry.getChildrenOf(entityDefinition)); @@ -229,11 +235,11 @@ private List findPossibleBaseEntities(EntityDefinition entityD /** * Given existing entity definition and a request for narrowing it, tries to find refined definition. */ - public EntityDefinition findRestrictedEntityDefinition(EntityDefinition baseEntityDefinition, QName specificTypeName) throws QueryException { + public JpaRootEntityDefinition findRestrictedEntityDefinition(JpaEntityDefinition baseEntityDefinition, QName specificTypeName) throws QueryException { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - EntityDefinition specificEntityDefinition = registry.findEntityDefinition(specificTypeName); + JpaRootEntityDefinition specificEntityDefinition = registry.findEntityDefinition(specificTypeName); if (!baseEntityDefinition.isAssignableFrom(specificEntityDefinition)) { - throw new QueryException("Entity " + baseEntityDefinition.getJpaName() + " cannot be restricted to " + specificEntityDefinition.getJpaName()); + throw new QueryException("Entity " + baseEntityDefinition + " cannot be restricted to " + specificEntityDefinition); } return specificEntityDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java index 81badc24024..25db321b1ac 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java @@ -17,30 +17,26 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import org.apache.commons.lang.Validate; /** * @author mederly */ -public class ProperDefinitionSearchResult extends DefinitionSearchResult { +public class ProperDefinitionSearchResult extends DefinitionSearchResult { - EntityDefinition entityDefinition; // entity in which the item was found + JpaEntityDefinition entityDefinition; // entity in which the item was found - public ProperDefinitionSearchResult(T itemDefinition, ItemPath remainder, EntityDefinition entityDefinition) { - super(itemDefinition, remainder); - Validate.notNull(entityDefinition, "entityDefinition"); - this.entityDefinition = entityDefinition; - } - - public ProperDefinitionSearchResult(EntityDefinition entityDefinition, DefinitionSearchResult result) { + public ProperDefinitionSearchResult(JpaEntityDefinition entityDefinition, DefinitionSearchResult result) { super(result.getItemDefinition(), result.getRemainder()); Validate.notNull(entityDefinition, "entityDefinition"); this.entityDefinition = entityDefinition; } - public EntityDefinition getEntityDefinition() { + public JpaEntityDefinition getEntityDefinition() { return entityDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java index 66042ac23a2..78522517d9c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -17,14 +17,18 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.ClassDefinitionParser; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.util.DebugDumpable; @@ -49,7 +53,7 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { private static final Trace LOGGER = TraceManager.getTrace(QueryDefinitionRegistry2.class); - private static final Map definitions; + private static final Map definitions; private static QueryDefinitionRegistry2 registry; @@ -57,8 +61,8 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { LOGGER.trace("Initializing query definition registry."); ClassDefinitionParser classDefinitionParser = new ClassDefinitionParser(); - Map map = new HashMap(); - Map, EntityDefinition> definitionsByClass = new HashMap<>(); + final Map map = new HashMap<>(); + final Map, JpaRootEntityDefinition> definitionsByClass = new HashMap<>(); Collection types = ClassMapper.getKnownTypes(); for (RObjectType type : types) { @@ -67,32 +71,48 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { continue; } - EntityDefinition definition = classDefinitionParser.parseObjectTypeClass(clazz); + JpaRootEntityDefinition definition = classDefinitionParser.parseRootClass(clazz); if (definition == null) { continue; } ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(type); map.put(objectType.getTypeQName(), definition); - definitionsByClass.put(definition.getJpaType(), definition); + definitionsByClass.put(definition.getJpaClass(), definition); } // TODO fix this hack - EntityDefinition caseDefinition = classDefinitionParser.parseObjectTypeClass(AccessCertificationCaseType.COMPLEX_TYPE, - AccessCertificationCaseType.class, RAccessCertificationCase.class); + JpaRootEntityDefinition caseDefinition = classDefinitionParser.parseRootClass(RAccessCertificationCase.class); map.put(AccessCertificationCaseType.COMPLEX_TYPE, caseDefinition); - // link parents (maybe not needed at all, we'll see) - for (EntityDefinition definition : map.values()) { - Class superclass = definition.getJpaType().getSuperclass(); - if (!RObject.class.isAssignableFrom(superclass)) { - continue; - } - EntityDefinition superclassDefinition = definitionsByClass.get(superclass); - if (superclassDefinition == null) { - throw new IllegalStateException("No definition for superclass " + superclass + " of " + definition); - } - definition.setSuperclassDefinition(superclassDefinition); + // link parents (maybe not needed at all, we'll see) and referenced entity definitions + for (final JpaRootEntityDefinition definition : map.values()) { + Visitor resolutionVisitor = new Visitor() { + @Override + public void visit(Visitable visitable) { + if (visitable instanceof JpaRootEntityDefinition) { + JpaRootEntityDefinition entityDef = ((JpaRootEntityDefinition) visitable); + Class superclass = entityDef.getJpaClass().getSuperclass(); + if (!RObject.class.isAssignableFrom(superclass)) { + return; + } + JpaRootEntityDefinition superclassDefinition = definitionsByClass.get(superclass); + if (superclassDefinition == null) { + throw new IllegalStateException("No definition for superclass " + superclass + " of " + entityDef); + } + entityDef.getContent().setSuperclassDefinition(superclassDefinition); + } else if (visitable instanceof JpaReferenceDefinition) { + JpaReferenceDefinition entRefDef = ((JpaReferenceDefinition) visitable); + Class referencedEntityJpaClass = entRefDef.getReferencedEntityJpaClass(); + JpaRootEntityDefinition realEntDef = definitionsByClass.get(referencedEntityJpaClass); + if (realEntDef == null) { + throw new IllegalStateException("Couldn't find entity definition for " + referencedEntityJpaClass); + } + entRefDef.setReferencedEntityDefinition(realEntDef); + } + } + }; + definition.accept(resolutionVisitor); } definitions = Collections.unmodifiableMap(map); @@ -121,18 +141,18 @@ public String debugDump() { public String debugDump(int indent) { StringBuilder builder = new StringBuilder(); DebugUtil.indentDebugDump(builder, indent); - Collection defCollection = definitions.values(); - for (Definition definition : defCollection) { + Collection defCollection = definitions.values(); + for (JpaRootEntityDefinition definition : defCollection) { builder.append(definition.debugDump()).append('\n'); } return builder.toString(); } - public EntityDefinition findEntityDefinition(QName typeName) { + public JpaRootEntityDefinition findEntityDefinition(QName typeName) { Validate.notNull(typeName, "Type name must not be null."); - EntityDefinition def = definitions.get(typeName); + JpaRootEntityDefinition def = definitions.get(typeName); if (def == null) { throw new IllegalStateException("Type " + typeName + " couldn't be found in type registry"); } @@ -140,7 +160,7 @@ public EntityDefinition findEntityDefinition(QName typeName) { } // always returns non-null value - public EntityDefinition findEntityDefinition(Class type) throws QueryException { + public JpaRootEntityDefinition findEntityDefinition(Class type) throws QueryException { Validate.notNull(type, "Type must not be null."); return findEntityDefinition(getQNameForType(type)); } @@ -155,10 +175,10 @@ public QName getQNameForType(Class type) throws Que throw new QueryException("Unsupported type " + type); } - public DefinitionSearchResult findDefinition(Class type, ItemPath path, Class definitionType) throws QueryException { + public DefinitionSearchResult findDefinition(Class type, ItemPath path, Class definitionType) throws QueryException { Validate.notNull(type, "Type must not be null."); Validate.notNull(definitionType, "Definition type must not be null."); - EntityDefinition entityDef = findEntityDefinition(type); + JpaRootEntityDefinition entityDef = findEntityDefinition(type); return entityDef.findDefinition(path, definitionType); } @@ -166,21 +186,21 @@ public DefinitionSearchResult * Returns possible "children" of a given definition. * More abstract classes are listed first. */ - public List getChildrenOf(EntityDefinition entityDefinition) { - List retval = new ArrayList<>(); - List children = getDirectChildrenOf(entityDefinition); - for (EntityDefinition child : children) { + public List getChildrenOf(JpaEntityDefinition entityDefinition) { + List retval = new ArrayList<>(); + List children = getDirectChildrenOf(entityDefinition); + for (JpaRootEntityDefinition child : children) { retval.add(child); retval.addAll(getChildrenOf(child)); } return retval; } - private List getDirectChildrenOf(EntityDefinition parentDefinition) { - Class parentClass = parentDefinition.getJpaType(); - List retval = new ArrayList<>(); - for (EntityDefinition definition : definitions.values()) { - if (parentClass.equals(definition.getJpaType().getSuperclass())) { + private List getDirectChildrenOf(JpaEntityDefinition parentDefinition) { + Class parentClass = parentDefinition.getJpaClass(); + List retval = new ArrayList<>(); + for (JpaRootEntityDefinition definition : definitions.values()) { + if (parentClass.equals(definition.getJpaClass().getSuperclass())) { retval.add(definition); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index add9f609d6a..2111ea65103 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -19,7 +19,6 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.AllFilter; import com.evolveum.midpoint.prism.query.AndFilter; @@ -38,13 +37,16 @@ import com.evolveum.midpoint.prism.query.UndefinedFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionSpecification; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -68,7 +70,6 @@ import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; import org.hibernate.Session; @@ -81,26 +82,26 @@ /** * Interprets midPoint queries by translating them to hibernate (HQL) ones. - * + *

* There are two parts: - * - filter translation, - * - paging translation. - * + * - filter translation, + * - paging translation. + *

* As for filter translation, we traverse the filter depth-first, creating an isomorphic structure of Restrictions. * While creating them, we continually build a set of entity references that are necessary to evaluate the query; * these references are in the form of cartesian join of entities from which each one can have a set of entities * connected to it via left outer join. An example: - * + *

* from - * RUser u - * left join u.assignments a with ... - * left join u.organization o, - * RRole r - * left join r.assignments a2 with ... - * + * RUser u + * left join u.assignments a with ... + * left join u.organization o, + * RRole r + * left join r.assignments a2 with ... + *

* This structure is maintained in InterpretationContext, namely in the HibernateQuery being prepared. (In order to * produce HQL, we use ad-hoc "hibernate query model" in hqm package, rooted in HibernateQuery class.) - * + *

* Paging translation is done after filters are translated. It may add some entity references as well, if they are not * already present. * @@ -193,7 +194,7 @@ private Restriction findAndCreateRestriction(T filter, LOGGER.trace("Determining restriction for filter {}", filter); InterpreterHelper helper = context.getHelper(); - EntityDefinition baseEntityDefinition; + JpaEntityDefinition baseEntityDefinition; if (parent != null) { baseEntityDefinition = parent.getBaseEntityDefinitionForChildren(); } else { @@ -205,7 +206,10 @@ private Restriction findAndCreateRestriction(T filter, return restriction; } - private Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext context, Restriction parent, InterpreterHelper helper, EntityDefinition baseEntityDefinition) throws QueryException { + private + Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext context, Restriction parent, + InterpreterHelper helper, JpaEntityDefinition baseEntityDefinition) throws QueryException { + // the order of processing restrictions can be important, so we do the selection via handwritten code if (filter instanceof AndFilter) { @@ -220,12 +224,12 @@ private Restriction findAndCreateRestrictionInternal(T return new OrgRestriction(context, (OrgFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof TypeFilter) { TypeFilter typeFilter = (TypeFilter) filter; - EntityDefinition refinedEntityDefinition = helper.findRestrictedEntityDefinition(baseEntityDefinition, typeFilter.getType()); + JpaEntityDefinition refinedEntityDefinition = helper.findRestrictedEntityDefinition(baseEntityDefinition, typeFilter.getType()); return new TypeRestriction(context, typeFilter, refinedEntityDefinition, parent); } else if (filter instanceof ExistsFilter) { ExistsFilter existsFilter = (ExistsFilter) filter; ItemPath path = existsFilter.getFullPath(); - ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, EntityDefinition.class); + ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, JpaEntityItemDefinition.class); if (searchResult == null) { throw new QueryException("Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity"); } @@ -233,7 +237,7 @@ private Restriction findAndCreateRestrictionInternal(T } else if (filter instanceof RefFilter) { RefFilter refFilter = (RefFilter) filter; ItemPath path = refFilter.getFullPath(); - ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, ReferenceDefinition.class); + ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, JpaReferenceDefinition.class); if (searchResult == null) { throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a reference item"); } @@ -243,11 +247,11 @@ private Restriction findAndCreateRestrictionInternal(T ValueFilter valFilter = (ValueFilter) filter; ItemPath path = valFilter.getFullPath(); - ProperDefinitionSearchResult propDefRes = helper.findProperDefinition(baseEntityDefinition, path, PropertyDefinition.class); + ProperDefinitionSearchResult propDefRes = helper.findProperDefinition(baseEntityDefinition, path, JpaPropertyDefinition.class); if (propDefRes != null) { return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getItemDefinition()); } - ProperDefinitionSearchResult anyDefRes = helper.findProperDefinition(baseEntityDefinition, path, AnyDefinition.class); + ProperDefinitionSearchResult anyDefRes = helper.findProperDefinition(baseEntityDefinition, path, JpaAnyDefinition.class); if (anyDefRes != null) { if (ItemPath.containsSingleNameSegment(anyDefRes.getRemainder())) { return new AnyPropertyRestriction(context, valFilter, anyDefRes.getEntityDefinition(), parent, anyDefRes.getItemDefinition()); @@ -265,14 +269,6 @@ private Restriction findAndCreateRestrictionInternal(T } } - private ItemPath getFullPath(Restriction parent, ItemPath fullPath) { - if (parent == null) { - return fullPath; - } else { - return new ItemPath(parent.getBaseItemPathForChildren(), fullPath); - } - } - private void interpretPagingAndSorting(InterpretationContext context, ObjectQuery query, boolean countingObjects) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String rootAlias = hibernateQuery.getPrimaryEntityAlias(); @@ -305,7 +301,8 @@ protected void updatePagingAndSortingByOid(RootHibernateQuery hibernateQuery, Ob } } - public void updatePagingAndSorting(InterpretationContext context, RootHibernateQuery hibernateQuery, ObjectPaging paging) throws QueryException { + public void updatePagingAndSorting(InterpretationContext context, RootHibernateQuery hibernateQuery, + ObjectPaging paging) throws QueryException { if (paging == null) { return; } @@ -325,28 +322,28 @@ public void updatePagingAndSorting(InterpretationConte } } - ProperDefinitionSearchResult result = context.getHelper().findProperDefinition( - context.getRootEntityDefinition(), orderByPath, Definition.class); + ProperDefinitionSearchResult result = context.getHelper().findProperDefinition( + context.getRootEntityDefinition(), orderByPath, JpaItemDefinition.class); if (result == null) { throw new QueryException("Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it."); - } else if (result.getItemDefinition() instanceof AnyDefinition) { + } else if (result.getItemDefinition() instanceof JpaAnyDefinition) { throw new QueryException("Sorting based on extension item or attribute is not supported yet: " + orderByPath); - } else if (result.getItemDefinition() instanceof ReferenceDefinition) { + } else if (result.getItemDefinition() instanceof JpaReferenceDefinition) { throw new QueryException("Sorting based on reference is not supported: " + orderByPath); - } else if (result.getItemDefinition().isCollection()) { + } else if (result.getItemDefinition().isMultivalued()) { throw new QueryException("Sorting based on multi-valued item is not supported: " + orderByPath); - } else if (result.getItemDefinition() instanceof EntityDefinition) { + } else if (result.getItemDefinition() instanceof JpaEntityItemDefinition) { throw new QueryException("Sorting based on entity is not supported: " + orderByPath); - } else if (!(result.getItemDefinition() instanceof PropertyDefinition)) { + } else if (!(result.getItemDefinition() instanceof JpaPropertyDefinition)) { throw new IllegalStateException("Unknown item definition type: " + result.getClass()); } - EntityDefinition baseEntityDefinition = result.getEntityDefinition(); - PropertyDefinition orderByDefinition = (PropertyDefinition) result.getItemDefinition(); + JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition(); + JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) result.getItemDefinition(); String hqlPropertyPath = context.getHelper().prepareJoins(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition) + "." + orderByDefinition.getJpaName(); - if (PolyString.class.equals(orderByDefinition.getJaxbType())) { + if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; } if (paging.getDirection() != null) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index aac26862e93..92ea20e82f8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -18,16 +18,13 @@ import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; import com.evolveum.midpoint.repo.sql.data.common.RObject; -import com.evolveum.midpoint.repo.sql.data.common.any.RAssignmentExtension; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.query.definition.Any; import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; -import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; -import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; -import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.apache.commons.lang.StringUtils; @@ -40,39 +37,33 @@ import javax.persistence.Lob; import javax.persistence.Transient; import javax.xml.namespace.QName; -import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.Set; /** * @author lazyman + * @author mederly */ public class ClassDefinitionParser { private static final Trace LOGGER = TraceManager.getTrace(ClassDefinitionParser.class); - public EntityDefinition parseObjectTypeClass(Class type) { - ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(type); - QName jaxbName = objectType.getQName(); - Class jaxbType = objectType.getClassDefinition(); - return parseObjectTypeClass(jaxbName, jaxbType, type); + public JpaRootEntityDefinition parseRootClass(Class jpaClass) { + JpaEntityContentDefinition content = parseClass(jpaClass); + JpaRootEntityDefinition rootEntityDefinition = new JpaRootEntityDefinition(jpaClass, content); + return rootEntityDefinition; } - public EntityDefinition parseObjectTypeClass(QName jaxbName, Class jaxbType, Class jpaType) { - EntityDefinition entityDefinition = new EntityDefinition(jaxbName, jaxbType, jpaType.getSimpleName(), jpaType, null); - updateEntityDefinition(entityDefinition); - return entityDefinition; - } + private JpaEntityContentDefinition parseClass(Class jpaClass) { - private void updateEntityDefinition(EntityDefinition entity) { + JpaEntityContentDefinition entity = new JpaEntityContentDefinition(); LOGGER.trace("### {}", entity); - addVirtualDefinitions(entity); - Method[] methods = entity.getJpaType().getMethods(); - - entity.setEmbedded(entity.getJpaType().getAnnotation(Embeddable.class) != null); + addVirtualDefinitions(jpaClass, entity); + Method[] methods = jpaClass.getMethods(); for (Method method : methods) { String methodName = method.getName(); @@ -87,42 +78,91 @@ private void updateEntityDefinition(EntityDefinition entity) { continue; } - LOGGER.trace("# {}", methodName); + LOGGER.trace("# {}", method); + JpaItemDefinition jpaItemDefinition = parseMethod(method); + entity.addDefinition(jpaItemDefinition); + } + return entity; + } + + private JpaItemDefinition parseMethod(Method method) { + CollectionSpecification collectionSpecification; // non-null if return type is Set, null if it's X + Type returnedContentType; // X in return type, which is either X or Set + if (Set.class.isAssignableFrom(method.getReturnType())) { + // e.g. Set or Set or Set> + Type returnType = method.getGenericReturnType(); + if (!(returnType instanceof ParameterizedType)) { + throw new IllegalStateException("Method " + method + " returns a non-parameterized collection"); + } + returnedContentType = ((ParameterizedType) returnType).getActualTypeArguments()[0]; + collectionSpecification = new CollectionSpecification(); + } else { + returnedContentType = method.getReturnType(); + collectionSpecification = null; + } + + QName jaxbName = getJaxbName(method); + String jpaName = getJpaName(method); + Class jpaClass = getClass(returnedContentType); + + // sanity check + if (Set.class.isAssignableFrom(jpaClass)) { + throw new IllegalStateException("Collection within collection is not supported: method=" + method); + } + + JpaItemDefinition definition; + Any any = (Any) jpaClass.getAnnotation(Any.class); + if (any != null) { + jaxbName = new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()); + definition = new JpaAnyDefinition(jaxbName, jpaName, jpaClass); + } else if (ObjectReference.class.isAssignableFrom(jpaClass)) { + boolean embedded = method.isAnnotationPresent(Embedded.class); + // computing referenced entity type from returned content type like RObjectReference or REmbeddedReference + Class referencedJpaClass; + if (returnedContentType instanceof ParameterizedType) { + referencedJpaClass = getClass(((ParameterizedType) returnedContentType).getActualTypeArguments()[0]); + } else { + referencedJpaClass = RObject.class; + } + definition = new JpaReferenceDefinition(jaxbName, jpaName, collectionSpecification, jpaClass, referencedJpaClass, embedded); + } else if (isEntity(jpaClass)) { + JpaEntityContentDefinition content = parseClass(jpaClass); + boolean embedded = method.isAnnotationPresent(Embedded.class) || jpaClass.isAnnotationPresent(Embeddable.class); + definition = new JpaEntityItemDefinition(jaxbName, jpaName, collectionSpecification, jpaClass, content, embedded); + } else { + boolean lob = method.isAnnotationPresent(Lob.class); + boolean enumerated = method.isAnnotationPresent(Enumerated.class); + //todo implement also lookup for @Table indexes + boolean indexed = method.isAnnotationPresent(Index.class); + definition = new JpaPropertyDefinition(jaxbName, jpaName, collectionSpecification, jpaClass, lob, enumerated, indexed); + } + return definition; + } - QName jaxbName = getJaxbName(method); - Class jaxbType = getJaxbType(method); - String jpaName = getJpaName(method); - Definition definition = createDefinition(jaxbName, jaxbType, jpaName, method, null); - entity.addDefinition(definition); + private Class getClass(Type type) { + if (type instanceof Class) { + return ((Class) type); + } else if (type instanceof ParameterizedType) { + return getClass(((ParameterizedType) type).getRawType()); + } else { + throw new IllegalStateException("Unsupported type: " + type); } } - private void addVirtualDefinitions(EntityDefinition entityDef) { - Class jpaType = entityDef.getJpaType(); - addVirtualDefinitionsForClass(entityDef, jpaType); + private void addVirtualDefinitions(Class jpaClass, JpaEntityContentDefinition entityDef) { + addVirtualDefinitionsForClass(jpaClass, entityDef); - while ((jpaType = jpaType.getSuperclass()) != null) { - addVirtualDefinitionsForClass(entityDef, jpaType); + while ((jpaClass = jpaClass.getSuperclass()) != null) { + addVirtualDefinitionsForClass(jpaClass, entityDef); } } - private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpaType) { - if (!jpaType.isAnnotationPresent(QueryEntity.class)) { + private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityContentDefinition entityDef) { + if (!jpaClass.isAnnotationPresent(QueryEntity.class)) { return; } - QueryEntity qEntity = (QueryEntity) jpaType.getAnnotation(QueryEntity.class); -// for (VirtualProperty property : qEntity.properties()) { -// QName jaxbName = createQName(property.jaxbName()); -// VirtualPropertyDefinition def = new VirtualPropertyDefinition(jaxbName, property.jaxbType(), -// property.jpaName(), property.jpaType()); -// def.setAdditionalParams(property.additionalParams()); -// entityDef.addDefinition(def); -// } -// -// for (VirtualReference reference : qEntity.references()) { -// -// } + QueryEntity qEntity = (QueryEntity) jpaClass.getAnnotation(QueryEntity.class); for (VirtualAny any : qEntity.anyElements()) { VirtualAnyDefinition def = new VirtualAnyDefinition( @@ -132,11 +172,12 @@ private void addVirtualDefinitionsForClass(EntityDefinition entityDef, Class jpa } for (VirtualCollection collection : qEntity.collections()) { - VirtualCollectionSpecification colSpec = new VirtualCollectionSpecification(); - colSpec.setAdditionalParams(collection.additionalParams()); - + // only collections of entities expected at this moment + VirtualCollectionSpecification colSpec = new VirtualCollectionSpecification(collection.additionalParams()); QName jaxbName = createQName(collection.jaxbName()); - Definition definition = createDefinition(jaxbName, collection.jaxbType(), collection.jpaName(), collection.collectionType(), colSpec); + String jpaName = collection.jpaName(); + JpaEntityContentDefinition content = parseClass(collection.jpaType()); + JpaEntityItemDefinition definition = new JpaEntityItemDefinition(jaxbName, jpaName, colSpec, jpaClass, content, false); entityDef.addDefinition(definition); } } @@ -145,110 +186,36 @@ private QName createQName(JaxbName name) { return new QName(name.namespace(), name.localPart()); } - private Definition createDefinition(QName jaxbName, Class jaxbType, String jpaName, AnnotatedElement object, CollectionSpecification collectionSpecification) { - Class jpaType = (object instanceof Class) ? (Class) object : ((Method) object).getReturnType(); - - if (Set.class.isAssignableFrom(jpaType)) { - if (collectionSpecification != null) { - throw new IllegalStateException("Collection within collection is not supported: jaxbName=" + - jaxbName + ", jaxbType=" + jaxbType + ", jpaName=" + jpaName + ", object=" + object); - } - collectionSpecification = new CollectionSpecification(); - if (object instanceof Method) { - Method method = (Method) object; - ParameterizedType type = (ParameterizedType) method.getGenericReturnType(); - Class clazz = (Class) type.getActualTypeArguments()[0]; - QName realJaxbName = getJaxbName(method); - Class realJaxbType = getJaxbType(clazz); - String realJpaName = getJpaName(method); - return createDefinition(realJaxbName, realJaxbType, realJpaName, clazz, collectionSpecification); - } else { - Class clazz = (Class) object; - Class realJaxbType = getJaxbType(clazz); - return createDefinition(jaxbName, realJaxbType, jpaName, clazz, collectionSpecification); - } - } - - Definition definition; - if (ObjectReference.class.isAssignableFrom(jpaType)) { - ReferenceDefinition refDef = new ReferenceDefinition(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); - definition = updateReferenceDefinition(refDef, object); - } else if (RAssignmentExtension.class.isAssignableFrom(jpaType)) { - definition = new AnyDefinition(jaxbName, jaxbType, jpaName, jpaType); - } else if (isEntity(object)) { - EntityDefinition entityDef = new EntityDefinition(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); - updateEntityDefinition(entityDef); - definition = entityDef; - } else { - PropertyDefinition propDef = new PropertyDefinition(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); - definition = updatePropertyDefinition(propDef, object); - } - - return definition; - } - - private boolean isEntity(AnnotatedElement object) { - Class type = (object instanceof Class) ? (Class) object : ((Method) object).getReturnType(); + private boolean isEntity(Class type) { if (RPolyString.class.isAssignableFrom(type)) { //it's hibernate entity but from prism point of view it's property return false; } - return type.getAnnotation(Entity.class) != null || type.getAnnotation(Embeddable.class) != null; } - private PropertyDefinition updatePropertyDefinition(PropertyDefinition definition, AnnotatedElement object) { - if (object.isAnnotationPresent(Lob.class)) { - definition.setLob(true); - } - - if (object.isAnnotationPresent(Enumerated.class)) { - definition.setEnumerated(true); - } - - //todo implement also lookup for @Table indexes - if (object.isAnnotationPresent(Index.class)) { - definition.setIndexed(true); - } - - return definition; - } - - private ReferenceDefinition updateReferenceDefinition(ReferenceDefinition definition, AnnotatedElement object) { - if (object.isAnnotationPresent(Embedded.class)) { - definition.setEmbedded(true); - } - - return definition; - } - private QName getJaxbName(Method method) { - QName name = new QName(SchemaConstantsGenerated.NS_COMMON, getPropertyName(method.getName())); if (method.isAnnotationPresent(JaxbName.class)) { JaxbName jaxbName = method.getAnnotation(JaxbName.class); - name = new QName(jaxbName.namespace(), jaxbName.localPart()); + return new QName(jaxbName.namespace(), jaxbName.localPart()); + } else { + return new QName(SchemaConstantsGenerated.NS_COMMON, getPropertyName(method.getName())); } - - return name; } - private Class getJaxbType(Method method) { - return getJaxbType(method.getReturnType()); - } - - private Class getJaxbType(Class clazz) { - if (RObject.class.isAssignableFrom(clazz)) { - ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(clazz); - return objectType.getClassDefinition(); - } - - if (clazz.getAnnotation(JaxbType.class) != null) { - JaxbType type = (JaxbType) clazz.getAnnotation(JaxbType.class); - return type.type(); - } - - return clazz; - } +// private Class getJaxbClass(Class clazz) { +// if (RObject.class.isAssignableFrom(clazz)) { +// ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(clazz); +// return objectType.getClassDefinition(); +// } +// +// if (clazz.getAnnotation(JaxbType.class) != null) { +// JaxbType type = (JaxbType) clazz.getAnnotation(JaxbType.class); +// return type.type(); +// } +// +// return clazz; +// } private String getJpaName(Method method) { String methodName = method.getName(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java index 617ec281b43..34b6d7c44e5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java @@ -24,8 +24,17 @@ import javax.xml.namespace.QName; /** - * @author lazyman + * In current version this is just a marker class - there's nothing to be said about standard collections yet. + * + * @author mederly */ public class CollectionSpecification { + public String toString() { + return "StdCol"; + } + + public String getShortInfo() { + return "[]"; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java deleted file mode 100644 index 73c2b5855ba..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/Definition.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; - -import javax.xml.namespace.QName; - -/** - * @author lazyman - */ -public abstract class Definition implements DebugDumpable { - - private static final Trace LOGGER = TraceManager.getTrace(Definition.class); - - //jaxb - private QName jaxbName; - private Class jaxbType; - //jpa - private String jpaName; - private Class jpaType; - - private CollectionSpecification collectionSpecification; - - public Definition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { - this.jaxbName = jaxbName; - this.jaxbType = jaxbType; - this.jpaName = jpaName; - this.jpaType = jpaType; - this.collectionSpecification = collectionSpecification; - } - - public QName getJaxbName() { - return jaxbName; - } - - public Class getJaxbType() { - return jaxbType; - } - - public String getJpaName() { - return jpaName; - } - - public Class getJpaType() { - return jpaType; - } - - protected void debugDumpExtended(StringBuilder builder, int indent) { - - } - - protected String dumpQName(QName qname) { - if (qname == null) { - return null; - } - - String namespace = qname.getNamespaceURI(); - namespace = namespace.replaceFirst("http://midpoint\\.evolveum\\.com/xml/ns/public", ".."); - - StringBuilder builder = new StringBuilder(); - builder.append('{'); - builder.append(namespace); - builder.append('}'); - builder.append(qname.getLocalPart()); - return builder.toString(); - } - - @Override - public String debugDump() { - return debugDump(0); - } - - @Override - public String debugDump(int indent) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < indent; i++) { - sb.append(DebugDumpable.INDENT_STRING); - } - sb.append(getDebugDumpClassName()); - sb.append('{'); - sb.append("jaxbN=").append(dumpQName(jaxbName)); - sb.append(", jaxbT=").append((jaxbType != null ? jaxbType.getSimpleName() : "")); - sb.append(", jpaN=").append(jpaName); - sb.append(", jpaT=").append((jpaType != null ? jpaType.getSimpleName() : "")); - if (collectionSpecification != null) { - sb.append(", coll=").append(collectionSpecification); // TODO - } - debugDumpExtended(sb, indent); - sb.append('}'); - - return sb.toString(); - } - - /** - * Return a human readable name of this class suitable for logs. - */ - protected abstract String getDebugDumpClassName(); - - /** - * Tries to find "next step" in the definition chain for a given ItemPath. - * Parts of the path that have no representation in the repository (e.g. metadata, - * construction) are simply skipped. - * - * @param path A path to be resolved. Always non-null and non-empty. - * @return - * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain - * and the unresolved remainder of the path. - * - If the search was not successful, returns null. - * - Note that for "Any" container returns the container entity definition itself plus the path that is to - * be searched in the given "Any" container. However, there's no point in repeating the search there, - * as it would yield the same result. - */ - public abstract DefinitionSearchResult nextDefinition(ItemPath path); - - /** - * Resolves the whole ItemPath. - * - * If successful, returns either: - * - correct definition + empty path, or - * - Any definition + path remainder - * - * If unsuccessful, return null. - * - * @return - */ - public DefinitionSearchResult findDefinition(ItemPath path, Class type) { - Definition currentDefinition = this; - for (;;) { - if (ItemPath.isNullOrEmpty(path)) { // we are at the end of search - hoping we found the correct class - if (type.isAssignableFrom(currentDefinition.getClass())) { - return new DefinitionSearchResult<>((D) currentDefinition, null); - } else { - return null; - } - } - if (currentDefinition instanceof AnyDefinition) { - if (type.isAssignableFrom(AnyDefinition.class)) { - return new DefinitionSearchResult<>((D) currentDefinition, path); - } else { - return null; - } - } - DefinitionSearchResult result = currentDefinition.nextDefinition(path); - if (result == null) { // oops - return null; - } - currentDefinition = result.getItemDefinition(); - path = result.getRemainder(); - } - } - - /** - * Translates ItemPath to a sequence of definitions. - * - * @param itemPath - * @return The translation (if successful) or null (if not successful). - * For "Any" elements, the last element in the path is Any. - * - * Note: structurally similar to findDefinition above - */ - - public DefinitionPath translatePath(ItemPath itemPath) { - Definition currentDefinition = this; - ItemPath originalPath = itemPath; // we remember original path just for logging - DefinitionPath definitionPath = new DefinitionPath(); - - for (;;) { - if (currentDefinition instanceof AnyDefinition || ItemPath.isNullOrEmpty(itemPath)) { - LOGGER.trace("ItemPath {} translated to DefinitionPath {} (started in {})", originalPath, definitionPath, this.getShortInfo()); - return definitionPath; - } - DefinitionSearchResult result = currentDefinition.nextDefinition(itemPath); - LOGGER.trace("nextDefinition on {} returned {}", itemPath, result != null ? result.getItemDefinition().getShortInfo() : "(null)"); - if (result == null) { - return null; // sorry we failed - } - currentDefinition = result.getItemDefinition(); - definitionPath.add(currentDefinition); - itemPath = result.getRemainder(); - } - } - - public String getShortInfo() { - return getDebugDumpClassName() + - (collectionSpecification != null ? "[]" : "") + - ":" + DebugUtil.formatElementName(getJaxbName()) + ":" + getJpaName(); - } - - public String toString() { - return getShortInfo(); - } - - public boolean isCollection() { - return collectionSpecification != null; - } - - public CollectionSpecification getCollectionSpecification() { - return collectionSpecification; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java index 592dcc39a91..b061fa8fdd3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java @@ -21,10 +21,10 @@ /** * @author lazyman */ -public class DefinitionComparator implements Comparator { +public class DefinitionComparator implements Comparator { @Override - public int compare(Definition o1, Definition o2) { + public int compare(JpaItemDefinition o1, JpaItemDefinition o2) { if (o1.getClass().equals(o2.getClass())) { return String.CASE_INSENSITIVE_ORDER.compare(o1.getJaxbName().getLocalPart(), o2.getJaxbName().getLocalPart()); @@ -33,21 +33,19 @@ public int compare(Definition o1, Definition o2) { return getType(o1) - getType(o2); } - private int getType(Definition def) { + private int getType(JpaItemDefinition def) { if (def == null) { return 0; } - - if (def instanceof PropertyDefinition) { + if (def instanceof JpaPropertyDefinition) { return 1; - } else if (def instanceof ReferenceDefinition) { + } else if (def instanceof JpaReferenceDefinition) { return 2; - } else if (def instanceof AnyDefinition) { + } else if (def instanceof JpaAnyDefinition) { return 4; - } else if (def instanceof EntityDefinition) { + } else if (def instanceof JpaEntityItemDefinition) { return 5; } - return 0; } } \ No newline at end of file diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java index 28d16d7c40e..bb1852fe8c7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java @@ -21,18 +21,31 @@ /** * A path of JPA definitions. Analogous to ItemPath; however, expresses the path in JPA terms, not prism terms. + * Auxiliary definitions (e.g. real EntityDefinition referenced by EntityReferenceDefinition) are NOT in such + * paths. I.e. path corresponds to the path of JPA (hibernate) names. + * + * Example: + * + * base entity = RUser + * prism path = assignment/target/link/activation/administrativeStatus (i.e. looks for admin status of a projection of e.g. assigned role) + * def path = + * Ent: assignment (RAssignment) + * Ref: target (real entity = RObject) + * Ref: link (real entity = RObject) + * Ent: activation + * Prop: administrativeStatus * * @author mederly */ public class DefinitionPath { - private List definitions = new ArrayList<>(); + private List definitions = new ArrayList<>(); - public void add(Definition definition) { + public void add(JpaItemDefinition definition) { definitions.add(definition); } - public List getDefinitions() { + public List getDefinitions() { return definitions; } @@ -40,33 +53,24 @@ public int size() { return definitions.size(); } - public Definition get(int i) { + public JpaItemDefinition get(int i) { return definitions.get(i); } - public AnyDefinition getAnyDefinition() { - for (Definition definition : definitions) { - if (definition instanceof AnyDefinition) { - return (AnyDefinition) definition; - } - } - return null; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('['); boolean first = true; - for (Definition definition : definitions) { + for (JpaItemDefinition definition : definitions) { if (first) { first = false; } else { sb.append(", "); } if (definition != null) { - sb.append(definition.getShortInfo()); + sb.append(definition); } else { sb.append("null"); // Just to catch errors in translations } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java similarity index 72% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java index 631b0a91352..b79b5151643 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/AnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; @@ -24,10 +25,10 @@ /** * @author lazyman */ -public class AnyDefinition extends Definition { +public class JpaAnyDefinition extends JpaItemDefinition { - public AnyDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType) { - super(jaxbName, jaxbType, jpaName, jpaType, null); + public JpaAnyDefinition(QName jaxbName, String jpaName, Class jpaClass) { + super(jaxbName, jpaName, null, jpaClass); // no collection specification for this kind of item } @Override @@ -43,4 +44,14 @@ public DefinitionSearchResult nextDefinition(ItemPath path) { // the definition. ;) return new DefinitionSearchResult(this, path); } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } + + @Override + protected void debugDumpExtended(StringBuilder sb, int indent) { + // nothing to put here + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java new file mode 100644 index 00000000000..1f34519587a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; + +/** + * Defines the content of item or standalone entity. + * + * @author mederly + */ +public abstract class JpaDefinition implements DebugDumpable, Visitable { + + private static final Trace LOGGER = TraceManager.getTrace(JpaDefinition.class); + + /** + * JPA class - either "composite" (RObject, RUser, RAssignment, ...) or "primitive" (String, Integer, int, ...) + */ + private Class jpaClass; + + public JpaDefinition(Class jpaClass) { + Validate.notNull(jpaClass, "jpaClass"); + this.jpaClass = jpaClass; + } + + public Class getJpaClass() { + return jpaClass; + } + + public String getJpaClassName() { + return jpaClass.getSimpleName(); + } + + /** + * Tries to find "next step" in the definition chain for a given ItemPath. + * Parts of the path that have no representation in the repository (e.g. metadata, + * construction) are simply skipped. + * + * @param path A path to be resolved. Always non-null and non-empty. + * @return + * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain + * and the unresolved remainder of the path. + * - If the search was not successful, returns null. + * - Note that for "Any" container returns the container entity definition itself plus the path that is to + * be searched in the given "Any" container. However, there's no point in repeating the search there, + * as it would yield the same result. + */ + public abstract DefinitionSearchResult nextDefinition(ItemPath path) throws QueryException; + + /** + * Resolves the whole ItemPath. + * + * If successful, returns either: + * - correct definition + empty path, or + * - Any definition + path remainder + * + * If unsuccessful, return null. + * + * @return + */ + public DefinitionSearchResult findDefinition(ItemPath path, Class type) throws QueryException { + JpaDefinition currentDefinition = this; + for (;;) { + if (ItemPath.isNullOrEmpty(path)) { // we are at the end of search - hoping we found the correct class + if (type.isAssignableFrom(currentDefinition.getClass())) { + return new DefinitionSearchResult<>((D) currentDefinition, null); + } else { + return null; + } + } + if (currentDefinition instanceof JpaAnyDefinition) { + if (type.isAssignableFrom(JpaAnyDefinition.class)) { + return new DefinitionSearchResult<>((D) currentDefinition, path); + } else { + return null; + } + } + DefinitionSearchResult result = currentDefinition.nextDefinition(path); + if (result == null) { // oops + return null; + } + currentDefinition = result.getItemDefinition(); + path = result.getRemainder(); + } + } + + /** + * Translates ItemPath to a sequence of definitions. + * + * @param itemPath + * @return The translation (if successful) or null (if not successful). + * For "Any" elements, the last element in the path is Any. + * + * Note: structurally similar to findDefinition above + */ + +// public DefinitionPath translatePath(ItemPath itemPath) throws QueryException { +// ItemPath originalPath = itemPath; // we remember original path just for logging +// DefinitionPath definitionPath = new DefinitionPath(); +// +// JpaDefinition currentDefinition = this; +// for (;;) { +// if (currentDefinition instanceof JpaAnyDefinition || ItemPath.isNullOrEmpty(itemPath)) { +// LOGGER.trace("ItemPath {} translated to DefinitionPath {} (started in {})", originalPath, definitionPath, this); +// return definitionPath; +// } +// DefinitionSearchResult result = currentDefinition.nextDefinition(itemPath); +// LOGGER.trace("nextDefinition on {} returned {}", itemPath, result != null ? result.getItemDefinition() : "(null)"); +// if (result == null) { +// return null; // sorry we failed +// } +// JpaItemDefinition nextDefinition = result.getItemDefinition(); +// definitionPath.add(nextDefinition); +// +// itemPath = result.getRemainder(); +// currentDefinition = nextDefinition; +// } +// } + + public String toString() { + return getDebugDumpClassName() + ":" + jpaClass.getSimpleName(); + } + + protected abstract String getDebugDumpClassName(); + + @Override + public String debugDump() { + return debugDump(0); + } + + protected String dumpQName(QName qname) { + if (qname == null) { + return null; + } + + String namespace = qname.getNamespaceURI(); + namespace = namespace.replaceFirst("http://midpoint\\.evolveum\\.com/xml/ns/public", ".."); + + StringBuilder builder = new StringBuilder(); + builder.append('{'); + builder.append(namespace); + builder.append('}'); + builder.append(qname.getLocalPart()); + return builder.toString(); + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java similarity index 53% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java index 86f3df1f395..61c64e371c1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/EntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java @@ -16,8 +16,15 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; +import com.evolveum.midpoint.prism.path.ParentPathSegment; +import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; @@ -28,123 +35,95 @@ import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; -import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collections; import java.util.List; /** - * @author lazyman + * + * @author mederly */ -public class EntityDefinition extends Definition { +public class JpaEntityContentDefinition implements DebugDumpable, Visitable { /** * child definitions of this entity */ - private List definitions; - private boolean embedded; - private EntityDefinition superclassDefinition; - - public EntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { - super(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); - Validate.notNull(jaxbName, "jaxbName"); - Validate.notNull(jaxbType, "jaxbType"); - Validate.notNull(jpaName, "jpaName"); - Validate.notNull(jpaType, "jpaType"); - } - - public boolean isEmbedded() { - return embedded; - } - - void setEmbedded(boolean embedded) { - this.embedded = embedded; - } + private List definitions; + private JpaRootEntityDefinition superclassDefinition; - public List getDefinitions() { + public void addDefinition(JpaItemDefinition definition) { if (definitions == null) { definitions = new ArrayList<>(); } - return Collections.unmodifiableList(definitions); - } - - public void addDefinition(Definition definition) { - if (definitions == null) { - definitions = new ArrayList<>(); - } - Definition oldDef = findDefinition(definition.getJaxbName(), Definition.class); + JpaItemDefinition oldDef = findDefinition(definition.getJaxbName(), JpaItemDefinition.class); if (oldDef != null) { definitions.remove(oldDef); } definitions.add(definition); - - Collections.sort(definitions, new DefinitionComparator()); } - @Override - protected void debugDumpExtended(StringBuilder builder, int indent) { - builder.append(", embedded=").append(isEmbedded()); - builder.append(", definitions=\n"); - - List definitions = getDefinitions(); - for (Definition definition : definitions) { - builder.append(definition.debugDump(indent+1)); - builder.append('\n'); - } - DebugUtil.indentDebugDump(builder, indent); // indentation before final '}' - } - - @Override - protected String getDebugDumpClassName() { - return "Ent"; - } - - private D findDefinition(QName jaxbName, Class type) { + public D findDefinition(QName jaxbName, Class type) { Validate.notNull(jaxbName, "Jaxb name must not be null."); Validate.notNull(type, "Definition type must not be null."); - for (Definition definition : getDefinitions()) { - if (!QNameUtil.match(jaxbName, definition.getJaxbName())){ - continue; - } + for (JpaItemDefinition definition : definitions) { + if (!QNameUtil.match(jaxbName, definition.getJaxbName())){ + continue; + } if (type.isAssignableFrom(definition.getClass())) { return (D) definition; } } - return null; } - @Override - public DefinitionSearchResult nextDefinition(ItemPath path) { + public void setSuperclassDefinition(JpaRootEntityDefinition superclassDefinition) { + this.superclassDefinition = superclassDefinition; + } + + public JpaRootEntityDefinition getSuperclassDefinition() { + return superclassDefinition; + } + + public DefinitionSearchResult nextDefinition(JpaEntityDefinition owningDefinition, ItemPath path) throws QueryException { - // first treat known discrepancies betweeen prism structure and repo representation: + // first treat known discrepancies between prism structure and repo representation: // metadata -> none, // construction/resourceRef -> resourceRef - while (skipFirstItem(path)) { + while (skipFirstItem(path, owningDefinition)) { path = path.tail(); } // now find the definition if (ItemPath.isNullOrEmpty(path)) { // note that for wrong input (e.g. path=metadata) this answer might be wrong, but we don't care - return new DefinitionSearchResult(this, null); + // return new DefinitionSearchResult(owningDefinition, null); + return null; } QName firstName = ((NameItemPathSegment) path.first()).getName(); - Definition def = findDefinition(firstName, Definition.class); - if (def != null) { - return new DefinitionSearchResult(def, path.tail()); - } else { + JpaItemDefinition def = findDefinition(firstName, JpaItemDefinition.class); + if (def == null) { return null; + } else { + return new DefinitionSearchResult(def, path.tail()); } } - private boolean skipFirstItem(ItemPath path) { + + private boolean skipFirstItem(ItemPath path, JpaEntityDefinition owningDefinition) throws QueryException { if (ItemPath.isNullOrEmpty(path)) { return false; } - QName firstName = ((NameItemPathSegment) path.first()).getName(); + ItemPathSegment first = path.first(); + if (first instanceof IdItemPathSegment) { + throw new QueryException("ID path segments are not allowed in query: " + path); + } else if (first instanceof ObjectReferencePathSegment) { + throw new QueryException("'@' path segment cannot be used in the context of an entity " + owningDefinition); + } else if (first instanceof ParentPathSegment) { + throw new UnsupportedOperationException("TODO"); + } + + QName firstName = ((NameItemPathSegment) first).getName(); // metadata -> null if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { @@ -165,19 +144,28 @@ private boolean skipFirstItem(ItemPath path) { return false; } - public boolean isAssignableFrom(EntityDefinition specificEntityDefinition) { - return getJpaType().isAssignableFrom(specificEntityDefinition.getJpaType()); - } - public boolean isAbstract() { - return Modifier.isAbstract(getJpaType().getModifiers()); + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + for (JpaItemDefinition definition : definitions) { + definition.accept(visitor); + } } - public void setSuperclassDefinition(EntityDefinition superclassDefinition) { - this.superclassDefinition = superclassDefinition; + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append("Superclass: ").append(superclassDefinition).append(", definitions (").append(definitions.size()).append("):\n"); + for (JpaItemDefinition definition : definitions) { + sb.append(definition.debugDump(indent+1)).append("\n"); + } + return sb.toString(); } - public EntityDefinition getSuperclassDefinition() { - return superclassDefinition; + @Override + public String debugDump() { + return debugDump(0); } } + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java new file mode 100644 index 00000000000..18d871e3086 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; + +/** + * @author mederly + */ +public interface JpaEntityDefinition { + + Class getJpaClass(); + + String getJpaClassName(); + + boolean isAbstract(); + + boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition); + + DefinitionSearchResult findDefinition(ItemPath path, Class clazz) throws QueryException; +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java new file mode 100644 index 00000000000..d6fef024cfd --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author lazyman + */ +public class JpaEntityItemDefinition extends JpaItemDefinition implements JpaEntityDefinition { + + private boolean embedded; + private JpaEntityContentDefinition content; + + public JpaEntityItemDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, Class jpaClass, JpaEntityContentDefinition content, boolean embedded) { + super(jaxbName, jpaName, collectionSpecification, jpaClass); + Validate.notNull(content, "content"); + this.content = content; + this.embedded = embedded; + } + + public boolean isEmbedded() { + return embedded; + } + + public JpaEntityContentDefinition getContent() { + return content; + } + + @Override + protected void debugDumpExtended(StringBuilder sb, int indent) { + sb.append(", embedded=").append(embedded).append("\n"); + sb.append(content.debugDump(indent + 1)); + } + + @Override + public DefinitionSearchResult nextDefinition(ItemPath path) throws QueryException { + return content.nextDefinition(this, path); + } + + @Override + protected String getDebugDumpClassName() { + return "Ent"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + content.accept(visitor); + } + + // the following methods are duplicate with JpaRootEntityDefinition + @Override + public boolean isAbstract() { + return Modifier.isAbstract(getJpaClass().getModifiers()); + } + + @Override + public boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition) { + return getJpaClass().isAssignableFrom(specificEntityDefinition.getJpaClass()); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java new file mode 100644 index 00000000000..469a5734b90 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.util.DebugUtil; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; + +/** + * Specifies an item - something that is included in an entity. + * + * @author mederly + */ +public abstract class JpaItemDefinition extends JpaDefinition { + + /** + * Name in ItemPath by which is this item to be retrieved. + */ + private QName jaxbName; + + /** + * Name that is used when constructing HQL queries. Must correspond to the name of Rxxx class property. + * Some virtual items (namely, object extension and shadow attributes; in future maybe metadata and construction) + * have no JPA name. They are accessed directly from their base entity. + */ + private String jpaName; + + /** + * Multiplicity and (optionally) parameters used to construct a join to retrieve the values. + */ + private CollectionSpecification collectionSpecification; + + public JpaItemDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, Class jpaClass) { + super(jpaClass); + Validate.notNull(jaxbName, "jaxbName"); + this.jaxbName = jaxbName; + this.jpaName = jpaName; + this.collectionSpecification = collectionSpecification; + } + + public QName getJaxbName() { + return jaxbName; + } + + public String getJpaName() { + return jpaName; + } + + public CollectionSpecification getCollectionSpecification() { + return collectionSpecification; + } + + public boolean isMultivalued() { + return collectionSpecification != null; + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append(getDebugDumpClassName()).append(": ").append(getJaxbName()); + if (collectionSpecification != null) { + sb.append(collectionSpecification.getShortInfo()); + } + sb.append(" => ").append(jpaName).append(" (").append(getJpaClass().getSimpleName()).append(")"); + debugDumpExtended(sb, indent); + return sb.toString(); + } + + protected abstract void debugDumpExtended(StringBuilder sb, int indent); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java deleted file mode 100644 index 6f77b302ab9..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaNamePath.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.util.ArrayList; -import java.util.List; - -/** - * A path of JPA names. Analogous to ItemPath; however, expresses the path in JPA terms, not prism terms. - * - * @author mederly - */ -public class JpaNamePath { - - private List names = new ArrayList<>(); - - public JpaNamePath(List names) { - this.names = names; - } - - public void add(String jpaName) { - names.add(jpaName); - } - - public List getNames() { - return names; - } - - @Override - public String toString() { - return "JpaNamePath{" + - "names=" + names + - '}'; - } - - public JpaNamePath allExceptLast() { - return new JpaNamePath(names.subList(0, names.size()-1)); - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java similarity index 76% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java index a5fdfb35ae4..170a9ba1e55 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; @@ -25,7 +26,7 @@ /** * @author lazyman */ -public class PropertyDefinition extends Definition { +public class JpaPropertyDefinition extends JpaItemDefinition { //jpa special types private boolean lob; @@ -33,8 +34,12 @@ public class PropertyDefinition extends Definition { //jpa special things private boolean indexed; - public PropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType, CollectionSpecification collectionSpecification) { - super(jaxbName, jaxbType, propertyName, propertyType, collectionSpecification); + public JpaPropertyDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, + Class jpaClass, boolean lob, boolean enumerated, boolean indexed) { + super(jaxbName, jpaName, collectionSpecification, jpaClass); + this.lob = lob; + this.enumerated = enumerated; + this.indexed = indexed; } public boolean isLob() { @@ -42,7 +47,7 @@ public boolean isLob() { } public boolean isPolyString() { - return RPolyString.class.equals(getJpaType()); + return RPolyString.class.equals(getJpaClass()); } public boolean isEnumerated() { @@ -82,4 +87,9 @@ public DefinitionSearchResult nextDefinition(ItemPath path) { // nowhere to come from here return null; } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java new file mode 100644 index 00000000000..735fa6299e3 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.PrismConstants; +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class JpaReferenceDefinition extends JpaItemDefinition { + + private JpaRootEntityDefinition referencedEntityDefinition; // lazily evaluated + private Class referencedEntityJpaClass; + private boolean embedded; + + public JpaReferenceDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, + Class jpaClass, Class referencedEntityJpaClass, boolean embedded) { + super(jaxbName, jpaName, collectionSpecification, jpaClass); + this.embedded = embedded; + Validate.notNull(referencedEntityJpaClass, "referencedEntityJpaClass"); + this.referencedEntityJpaClass = referencedEntityJpaClass; + } + + public boolean isEmbedded() { + return embedded; + } + + void setEmbedded(boolean embedded) { + this.embedded = embedded; + } + + @Override + protected void debugDumpExtended(StringBuilder builder, int indent) { + builder.append(", embedded=").append(isEmbedded()).append(", referencedEntity: ").append(referencedEntityDefinition); + } + + @Override + protected String getDebugDumpClassName() { + return "Ref"; + } + + @Override + public DefinitionSearchResult nextDefinition(ItemPath path) { + if (path.first() instanceof ObjectReferencePathSegment) { + // returning artificially created item definition, used to allow dereferencing target object in a generic way + return new DefinitionSearchResult( + new JpaEntityItemDefinition(PrismConstants.T_OBJECT_REFERENCE, "target", null, + referencedEntityDefinition.getJpaClass(), referencedEntityDefinition.getContent(), false), + path.tail()); + } else { + return null; + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } + + public void setReferencedEntityDefinition(JpaRootEntityDefinition realEntDef) { + this.referencedEntityDefinition = realEntDef; + } + + public JpaRootEntityDefinition getReferencedEntityDefinition() { + return referencedEntityDefinition; + } + + public Class getReferencedEntityJpaClass() { + return referencedEntityJpaClass; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java new file mode 100644 index 00000000000..3dc2085c071 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import com.evolveum.midpoint.util.DebugUtil; +import org.apache.commons.lang.Validate; + +import java.lang.reflect.Modifier; + +/** + * @author mederly + */ +public class JpaRootEntityDefinition extends JpaDefinition implements JpaEntityDefinition { + + private JpaEntityContentDefinition content; + + public JpaRootEntityDefinition(Class jpaClass, JpaEntityContentDefinition content) { + super(jpaClass); + Validate.notNull(content, "content"); + this.content = content; + } + + public JpaEntityContentDefinition getContent() { + return content; + } + + public boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition) { + return getJpaClass().isAssignableFrom(specificEntityDefinition.getJpaClass()); + } + + public boolean isAbstract() { + return Modifier.isAbstract(getJpaClass().getModifiers()); + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + content.accept(visitor); + } + + @Override + protected String getDebugDumpClassName() { + return "RootEnt"; + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append(getDebugDumpClassName()).append(":").append(getJpaClass().getSimpleName()).append(":\n"); + sb.append(content.debugDump(indent + 1)); + return sb.toString(); + } + + @Override + public DefinitionSearchResult nextDefinition(ItemPath path) throws QueryException { + return content.nextDefinition(this, path); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java deleted file mode 100644 index 4c1661d1a32..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/PathTranslation.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query.restriction; - -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.definition.DefinitionPath; - -/** - * @author Pavol - */ -public class PathTranslation { - private DefinitionPath definitionPath; - private ItemPath itemPathRemainder; - - public PathTranslation(DefinitionPath definitionPath, ItemPath itemPathRemainder) { - this.definitionPath = definitionPath; - this.itemPathRemainder = itemPathRemainder; - } - - public boolean isComplete() { - return ItemPath.isNullOrEmpty(itemPathRemainder); - } - - public DefinitionPath getDefinitionPath() { - return definitionPath; - } - - public ItemPath getItemPathRemainder() { - return itemPathRemainder; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java deleted file mode 100644 index 42286ac9c19..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ReferenceDefinition.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; - -import javax.xml.namespace.QName; - -/** - * @author lazyman - */ -public class ReferenceDefinition extends Definition { - - private boolean embedded; - - public ReferenceDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { - super(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); - } - - public boolean isEmbedded() { - return embedded; - } - - void setEmbedded(boolean embedded) { - this.embedded = embedded; - } - - @Override - protected void debugDumpExtended(StringBuilder builder, int indent) { - builder.append(", embedded=").append(isEmbedded()); - } - - @Override - protected String getDebugDumpClassName() { - return "Ref"; - } - - @Override - public DefinitionSearchResult nextDefinition(ItemPath path) { - // nowhere to come from here - return null; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java index f3998685d6c..ff2b155ba0f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import org.apache.commons.lang.Validate; @@ -24,12 +25,12 @@ /** * @author mederly */ -public class VirtualAnyDefinition extends AnyDefinition { +public class VirtualAnyDefinition extends JpaAnyDefinition { private RObjectExtensionType ownerType; // ObjectType (for extension) or ShadowType (for attributes) public VirtualAnyDefinition(QName jaxbName, RObjectExtensionType ownerType) { - super(jaxbName, null, null, null); + super(jaxbName, null, RObject.class); // RObject is artificial - don't want to make jpaClass nullable just for this single situation Validate.notNull(ownerType, "ownerType"); this.ownerType = ownerType; } @@ -37,4 +38,14 @@ public VirtualAnyDefinition(QName jaxbName, RObjectExtensionType ownerType) { public RObjectExtensionType getOwnerType() { return ownerType; } + + @Override + protected String getDebugDumpClassName() { + return "VirtualAny"; + } + + @Override + protected void debugDumpExtended(StringBuilder sb, int indent) { + sb.append(", ownerType=").append(ownerType); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java index e50ae3b92c8..f02158faf97 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualCollectionSpecification.java @@ -18,7 +18,8 @@ import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; -import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.List; /** * @author lazyman @@ -27,7 +28,8 @@ public class VirtualCollectionSpecification extends CollectionSpecification { private VirtualQueryParam[] additionalParams; - public VirtualCollectionSpecification() { + public VirtualCollectionSpecification(VirtualQueryParam[] additionalParams) { + this.additionalParams = additionalParams; } public VirtualQueryParam[] getAdditionalParams() { @@ -38,4 +40,21 @@ void setAdditionalParams(VirtualQueryParam[] additionalParams) { this.additionalParams = additionalParams; } + @Override + public String toString() { + return "VirtualCol{additionalParams=" + getAdditionalParamNames() + "}"; + } + + @Override + public String getShortInfo() { + return "[params=" + getAdditionalParamNames() + "]"; + } + + private List getAdditionalParamNames() { + List rv = new ArrayList<>(); + for (VirtualQueryParam p : additionalParams) { + rv.add(p.name()); + } + return rv; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java deleted file mode 100644 index 014dafc5f92..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualEntityDefinition.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; - -import javax.xml.namespace.QName; - -/** - * @author lazyman - */ -public class VirtualEntityDefinition extends EntityDefinition { - - private VirtualQueryParam[] additionalParams; - - public VirtualEntityDefinition(QName jaxbName, Class jaxbType, String jpaName, Class jpaType, CollectionSpecification collectionSpecification) { - super(jaxbName, jaxbType, jpaName, jpaType, collectionSpecification); - } - - public VirtualQueryParam[] getAdditionalParams() { - return additionalParams; - } - - void setAdditionalParams(VirtualQueryParam[] additionalParams) { - this.additionalParams = additionalParams; - } - - @Override - protected void debugDumpExtended(StringBuilder builder, int indent) { - super.debugDumpExtended(builder, indent); - - builder.append(", params=").append(additionalParams.length); - } - - @Override - protected String getDebugDumpClassName() { - return "VirtualEnt"; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java deleted file mode 100644 index d5f03ea3baa..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualPropertyDefinition.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; - -import javax.xml.namespace.QName; - -/** - * @author lazyman - */ -public class VirtualPropertyDefinition extends PropertyDefinition { - - private VirtualQueryParam[] additionalParams; - - public VirtualPropertyDefinition(QName jaxbName, Class jaxbType, String propertyName, Class propertyType, CollectionSpecification collectionSpecification) { - super(jaxbName, jaxbType, propertyName, propertyType, collectionSpecification); - } - - public VirtualQueryParam[] getAdditionalParams() { - return additionalParams; - } - - void setAdditionalParams(VirtualQueryParam[] additionalParams) { - this.additionalParams = additionalParams; - } - - @Override - protected void debugDumpExtended(StringBuilder builder, int indent) { - super.debugDumpExtended(builder, indent); - - builder.append(", params=").append(additionalParams.length); - } - - @Override - protected String getDebugDumpClassName() { - return "VirtualProp"; - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index 9c59af12c32..cb6c51ceccb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -19,20 +19,15 @@ import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.QueryDefinitionRegistry2; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; -import com.evolveum.midpoint.repo.sql.util.RUtil; import org.apache.commons.lang.Validate; -import org.hibernate.Query; -import org.hibernate.transform.ResultTransformer; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * Query in HQL that is being created. @@ -53,21 +48,11 @@ public abstract class HibernateQuery { * Or, * RUser u * left join u.assignments a with ... + * + * (originally, we thought about cross-joins with other entities, hence "primary entity") */ private EntityReference primaryEntity; // not null - /** - * All other entities for this query, again along with joined entities. - * For example, if we want to look for a name of assigned entity, i.e. - * UserType: Equal (assignment/target/name, 'Role1'), primary entity is: - * RUser u - * left join u.assignments a with ... - * and secondary one is: - * RObject o - * (with associated condition of o.oid = a.targetRef.targetOid) - */ - private List otherEntities = new ArrayList<>(); - /** * List of conditions in the "where" clause. They are to be interpreted as a conjunction. */ @@ -76,7 +61,7 @@ public abstract class HibernateQuery { private String orderByProperty; private OrderDirection orderDirection; - public HibernateQuery(EntityDefinition primaryEntityDef) { + public HibernateQuery(JpaRootEntityDefinition primaryEntityDef) { Validate.notNull(primaryEntityDef, "primaryEntityDef"); primaryEntity = createItemSpecification(primaryEntityDef); } @@ -116,10 +101,6 @@ public String getAsHqlText(int indent) { indent(sb, indent); sb.append("from\n"); primaryEntity.dumpToHql(sb, indent + 1); - for (EntityReference otherEntity : otherEntities) { - sb.append(",\n"); - otherEntity.dumpToHql(sb, indent+1); - } if (!conditions.isEmpty()) { sb.append("\n"); @@ -148,22 +129,26 @@ public static void indent(StringBuilder sb, int indent) { } } - public EntityReference createItemSpecification(EntityDefinition entityDef) { + public EntityReference createItemSpecification(JpaEntityDefinition entityDef) { String alias = createAlias(entityDef); - return new EntityReference(alias, entityDef.getJpaName()); + return new EntityReference(alias, entityDef.getJpaClassName()); + } + + public String createAlias(JpaEntityDefinition def) { + return createAlias(def.getJpaClassName(), true); } - public String createAlias(Definition def) { - return createAlias(def.getJpaName()); + public String createAlias(JpaItemDefinition joinedItemDef) { + return createAlias(joinedItemDef.getJpaName(), false); } private static final int LIMIT = 100; - public String createAlias(String name) { + public String createAlias(String name, boolean entity) { String prefix; //we want to skip 'R' prefix for entity definition names (a bit of hack) - int prefixIndex = name.startsWith("R") ? 1 : 0; + int prefixIndex = entity ? 1 : 0; prefix = Character.toString(name.charAt(prefixIndex)).toLowerCase(); int index = 2; @@ -185,11 +170,6 @@ private boolean hasAlias(String alias) { if (primaryEntity != null && primaryEntity.containsAlias(alias)) { return true; } - for (EntityReference other : otherEntities) { - if (other.containsAlias(alias)) { - return true; - } - } return false; } @@ -205,13 +185,13 @@ public void setOrder(String propertyPath, OrderDirection direction) { public abstract RootHibernateQuery getRootQuery(); // used to narrow the primary entity e.g. from RObject to RUser (e.g. during ItemValueRestriction processing) - public void narrowPrimaryEntity(EntityDefinition newDefinition) throws QueryException { + public void narrowPrimaryEntity(JpaRootEntityDefinition newDefinition) throws QueryException { String oldEntityName = getPrimaryEntity().getName(); Class oldEntityClass = ClassMapper.getHqlClassForHqlName(oldEntityName); - Class newEntityClass = newDefinition.getJpaType(); + Class newEntityClass = newDefinition.getJpaClass(); if (!(oldEntityClass.isAssignableFrom(newEntityClass))) { throw new QueryException("Cannot narrow primary entity definition from " + oldEntityClass + " to " + newEntityClass); } - getPrimaryEntity().setName(newDefinition.getJpaName()); // alias stays the same + getPrimaryEntity().setName(newDefinition.getJpaClassName()); // alias stays the same } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java index c5e551b40d2..b656297cf02 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java @@ -16,7 +16,8 @@ package com.evolveum.midpoint.repo.sql.query2.hqm; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; @@ -50,7 +51,7 @@ public class RootHibernateQuery extends HibernateQuery { private Integer firstResult; private ResultTransformer resultTransformer; - public RootHibernateQuery(EntityDefinition primaryEntityDef) { + public RootHibernateQuery(JpaRootEntityDefinition primaryEntityDef) { super(primaryEntityDef); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java index b3fd1c85ecc..abc0aefa53a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java @@ -16,7 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import org.apache.commons.lang.Validate; @@ -28,7 +28,7 @@ public class HibernateSubquery extends HibernateQuery { private HibernateQuery parentQuery; - public HibernateSubquery(EntityDefinition primaryEntityDef, HibernateQuery parentQuery) { + public HibernateSubquery(JpaRootEntityDefinition primaryEntityDef, HibernateQuery parentQuery) { super(primaryEntityDef); Validate.notNull(parentQuery); this.parentQuery = parentQuery; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java index 9d0649921dd..2c0d93255d2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AndRestriction.java @@ -16,12 +16,10 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -31,7 +29,7 @@ */ public class AndRestriction extends NaryLogicalRestriction { - public AndRestriction(InterpretationContext context, AndFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public AndRestriction(InterpretationContext context, AndFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index 79a57c7cf65..92a6fc38483 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -17,8 +17,6 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.data.common.any.RAnyConverter; @@ -26,14 +24,14 @@ import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.AnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; @@ -45,13 +43,13 @@ public class AnyPropertyRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(AnyPropertyRestriction.class); - private AnyDefinition anyDefinition; + private JpaAnyDefinition jpaAnyDefinition; - public AnyPropertyRestriction(InterpretationContext context, ValueFilter filter, EntityDefinition baseEntityDefinition, - Restriction parent, AnyDefinition anyDefinition) { + public AnyPropertyRestriction(InterpretationContext context, ValueFilter filter, JpaEntityDefinition baseEntityDefinition, + Restriction parent, JpaAnyDefinition jpaAnyDefinition) { super(context, filter, baseEntityDefinition, parent); - Validate.notNull(anyDefinition, "anyDefinition"); - this.anyDefinition = anyDefinition; + Validate.notNull(jpaAnyDefinition, "anyDefinition"); + this.jpaAnyDefinition = jpaAnyDefinition; } @Override @@ -66,8 +64,8 @@ public Condition interpretInternal(String hqlPath) throws QueryException { } RObjectExtensionType ownerType; - if (anyDefinition instanceof VirtualAnyDefinition) { - ownerType = ((VirtualAnyDefinition) anyDefinition).getOwnerType(); + if (jpaAnyDefinition instanceof VirtualAnyDefinition) { + ownerType = ((VirtualAnyDefinition) jpaAnyDefinition).getOwnerType(); } else { ownerType = null; // assignment extension has no ownerType } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java index e8e59a419eb..c3d772f37d1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java @@ -21,7 +21,7 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import org.apache.commons.lang.Validate; @@ -36,15 +36,15 @@ public class ExistsRestriction extends ItemRestriction { * * TODO think out the process of refinement of entity definition e.g. RObject->RUser */ - private EntityDefinition baseEntityDefinitionForChildren; + private JpaEntityDefinition baseEntityDefinitionForChildren; /** * HQL path to be used for child restrictions. */ private String baseHqlPathForChildren; - public ExistsRestriction(InterpretationContext context, ExistsFilter filter, EntityDefinition baseEntityDefinition, - Restriction parent, EntityDefinition baseEntityDefinitionForChildren) { + public ExistsRestriction(InterpretationContext context, ExistsFilter filter, JpaEntityDefinition baseEntityDefinition, + Restriction parent, JpaEntityDefinition baseEntityDefinitionForChildren) { super(context, filter, baseEntityDefinition, parent); Validate.notNull(baseEntityDefinitionForChildren, "baseEntityDefinitionForChildren"); this.baseEntityDefinitionForChildren = baseEntityDefinitionForChildren; @@ -70,7 +70,7 @@ public ItemPath getBaseItemPathForChildren() { } @Override - public EntityDefinition getBaseEntityDefinitionForChildren() { + public JpaEntityDefinition getBaseEntityDefinitionForChildren() { return baseEntityDefinitionForChildren; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java index 96835434afb..6f0cd01f390 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java @@ -16,13 +16,13 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.query.InOidFilter; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.container.Container; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import java.util.ArrayList; import java.util.Collection; @@ -33,7 +33,7 @@ */ public class InOidRestriction extends Restriction { - public InOidRestriction(InterpretationContext context, InOidFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public InOidRestriction(InterpretationContext context, InOidFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } @@ -46,10 +46,10 @@ public Condition interpret() throws QueryException { if (filter.isConsiderOwner()) { hqlPath += "ownerOid"; idValues = filter.getOids(); - } else if (ObjectType.class.isAssignableFrom(baseEntityDefinition.getJaxbType())) { + } else if (RObject.class.isAssignableFrom(baseEntityDefinition.getJpaClass())) { hqlPath += "oid"; idValues = filter.getOids(); - } else if (Containerable.class.isAssignableFrom(baseEntityDefinition.getJaxbType())) { + } else if (Container.class.isAssignableFrom(baseEntityDefinition.getJpaClass())) { hqlPath += "id"; // quite a hack idValues = toIntList(filter.getOids()); } else { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index db156d2985f..86f196cbacf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -17,16 +17,15 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; /** * @author mederly */ public abstract class ItemRestriction extends Restriction { - public ItemRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public ItemRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java index a0626e17e1e..e2933049c4c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -26,12 +26,13 @@ import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -51,7 +52,6 @@ * Abstract superclass for all value-related filters. There are two major problems solved: * 1) mapping from ItemPath to HQL property paths * 2) adding joined entities to the query, along with necessary conditions - * (there are two kinds of joins: left outer join and carthesian join) * * After the necessary entity is available, the fine work (creating one or more conditions * to execute the filtering) is done by subclasses of this path in the interpretInternal(..) method. @@ -63,7 +63,7 @@ public abstract class ItemValueRestriction extends ItemRe private static final Trace LOGGER = TraceManager.getTrace(ItemValueRestriction.class); - public ItemValueRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public ItemValueRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } @@ -131,7 +131,7 @@ protected Object getValue(List values) { return null; } - protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) throws QueryException { + protected Object getValueFromFilter(ValueFilter filter, JpaPropertyDefinition def) throws QueryException { Object value; if (filter instanceof PropertyValueFilter) { value = getValue(((PropertyValueFilter) filter).getValues()); @@ -139,20 +139,22 @@ protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); } - Class expectedType = def.getJaxbType(); + Class expectedType = def.getJpaClass(); if (expectedType.isPrimitive()) { expectedType = ClassUtils.primitiveToWrapper(expectedType); + } else if (expectedType.equals(RPolyString.class)) { + expectedType = PolyString.class; } //todo remove after some time [lazyman] //attempt to fix value type for polystring (if it was string in filter we create polystring from it) if (PolyString.class.equals(expectedType) && (value instanceof String)) { - LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", new Object[]{filter}); + LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", filter); value = new PolyString((String) value, (String) value); } //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) if (PolyString.class.equals(expectedType) && (value instanceof PolyStringType)) { - LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", new Object[]{filter}); + LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", filter); PolyStringType type = (PolyStringType) value; value = new PolyString(type.getOrig(), type.getNorm()); } @@ -168,7 +170,7 @@ protected Object getValueFromFilter(ValueFilter filter, PropertyDefinition def) } if (def.isEnumerated()) { - value = getRepoEnumValue((Enum) value, def.getJpaType()); + value = getRepoEnumValue((Enum) value, def.getJpaClass()); } return value; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java index e4da5d89081..6d758904fe5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/LogicalRestriction.java @@ -18,14 +18,14 @@ import com.evolveum.midpoint.prism.query.LogicalFilter; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; /** * @author lazyman */ public abstract class LogicalRestriction extends Restriction { - public LogicalRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public LogicalRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java index a6470ce20a9..aa3e8c29b20 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java @@ -21,7 +21,8 @@ import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.JunctionCondition; import com.evolveum.midpoint.util.logging.Trace; @@ -38,7 +39,7 @@ public abstract class NaryLogicalRestriction extend private static final Trace LOGGER = TraceManager.getTrace(NaryLogicalRestriction.class); private List restrictions; - public NaryLogicalRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public NaryLogicalRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java index e46202edb4e..4c13e5dd080 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NotRestriction.java @@ -16,21 +16,18 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NotFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.NotCondition; /** * @author lazyman */ public class NotRestriction extends UnaryLogicalRestriction { - public NotRestriction(InterpretationContext context, NotFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public NotRestriction(InterpretationContext context, NotFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java index e638215c7ce..fa70d1a5b7c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrRestriction.java @@ -19,7 +19,7 @@ import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; @@ -29,7 +29,7 @@ */ public class OrRestriction extends NaryLogicalRestriction { - public OrRestriction(InterpretationContext context, OrFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public OrRestriction(InterpretationContext context, OrFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java index 89eec446097..59721e8e475 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -20,7 +20,7 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -29,7 +29,7 @@ */ public class OrgRestriction extends Restriction { - public OrgRestriction(InterpretationContext context, OrgFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public OrgRestriction(InterpretationContext context, OrgFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index c3413e7cda6..262187df513 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -19,8 +19,8 @@ import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.PropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -33,29 +33,29 @@ public class PropertyRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(PropertyRestriction.class); - PropertyDefinition propertyDefinition; + JpaPropertyDefinition jpaPropertyDefinition; - public PropertyRestriction(InterpretationContext context, ValueFilter filter, EntityDefinition baseEntityDefinition, - Restriction parent, PropertyDefinition propertyDefinition) { + public PropertyRestriction(InterpretationContext context, ValueFilter filter, JpaEntityDefinition baseEntityDefinition, + Restriction parent, JpaPropertyDefinition jpaPropertyDefinition) { super(context, filter, baseEntityDefinition, parent); - Validate.notNull(propertyDefinition, "propertyDefinition"); - this.propertyDefinition = propertyDefinition; + Validate.notNull(jpaPropertyDefinition, "propertyDefinition"); + this.jpaPropertyDefinition = jpaPropertyDefinition; } @Override public Condition interpretInternal(String hqlPath) throws QueryException { - if (propertyDefinition.isLob()) { - throw new QueryException("Can't query based on clob property value '" + propertyDefinition + "'."); + if (jpaPropertyDefinition.isLob()) { + throw new QueryException("Can't query based on clob property value '" + jpaPropertyDefinition + "'."); } String propertyFullName; - if (propertyDefinition.isCollection()) { + if (jpaPropertyDefinition.isMultivalued()) { propertyFullName = hqlPath; } else { - propertyFullName = hqlPath + "." + propertyDefinition.getJpaName(); + propertyFullName = hqlPath + "." + jpaPropertyDefinition.getJpaName(); } - Object value = getValueFromFilter(filter, propertyDefinition); + Object value = getValueFromFilter(filter, jpaPropertyDefinition); Condition condition = createCondition(propertyFullName, value, filter); return addIsNotNullIfNecessary(condition, propertyFullName); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index 1bc1e951fd6..99121a808c9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -21,12 +21,11 @@ import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.CollectionSpecification; -import com.evolveum.midpoint.repo.sql.query2.definition.Definition; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.ReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -47,11 +46,10 @@ public class ReferenceRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(ReferenceRestriction.class); // Definition of the item being queried. - // We cannot expect ReferenceDefinition here, because of multivalued references (e.g. linkRef) that have CollectionDefinition. - private final Definition itemDefinition; + private final JpaReferenceDefinition itemDefinition; - public ReferenceRestriction(InterpretationContext context, RefFilter filter, EntityDefinition baseEntityDefinition, - Restriction parent, Definition itemDefinition) { + public ReferenceRestriction(InterpretationContext context, RefFilter filter, JpaEntityDefinition baseEntityDefinition, + Restriction parent, JpaReferenceDefinition itemDefinition) { super(context, filter, baseEntityDefinition, parent); Validate.notNull(itemDefinition, "itemDefinition"); this.itemDefinition = itemDefinition; @@ -75,7 +73,7 @@ public Condition interpretInternal(String hqlPath) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String propertyFullNamePrefix; - if (itemDefinition.isCollection()) { + if (itemDefinition.isMultivalued()) { propertyFullNamePrefix = hqlPath + "."; } else { propertyFullNamePrefix = hqlPath + "." + itemDefinition.getJpaName() + "."; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index 2af41a7a1eb..f3948e01073 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -19,11 +19,11 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpreterHelper; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import org.apache.commons.lang.Validate; import org.hibernate.Session; @@ -68,9 +68,9 @@ public abstract class Restriction { * Actually, the caller has to determine it, because it needs it to know what restriction to instantiate. * (TODO reconsider this) */ - protected EntityDefinition baseEntityDefinition; + protected JpaEntityDefinition baseEntityDefinition; - public Restriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public Restriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { Validate.notNull(context, "context"); Validate.notNull(filter, "filter"); Validate.notNull(baseEntityDefinition, "baseEntityDefinition"); @@ -177,11 +177,11 @@ protected ItemPath getFullPath(ItemPath path) { return new ItemPath(parent.getBaseItemPath(), path); } - public EntityDefinition getBaseEntityDefinition() { + public JpaEntityDefinition getBaseEntityDefinition() { return baseEntityDefinition; } - public EntityDefinition getBaseEntityDefinitionForChildren() { + public JpaEntityDefinition getBaseEntityDefinitionForChildren() { return getBaseEntityDefinition(); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java index 58ae82e5dd8..e33ff366236 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -22,7 +22,8 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; @@ -37,7 +38,7 @@ */ public class TypeRestriction extends Restriction { - public TypeRestriction(InterpretationContext context, TypeFilter filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public TypeRestriction(InterpretationContext context, TypeFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java index eaaddffbec7..7041cd24c1b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java @@ -20,7 +20,8 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; -import com.evolveum.midpoint.repo.sql.query2.definition.EntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -32,7 +33,7 @@ public abstract class UnaryLogicalRestriction exte private static final Trace LOGGER = TraceManager.getTrace(UnaryLogicalRestriction.class); - public UnaryLogicalRestriction(InterpretationContext context, T filter, EntityDefinition baseEntityDefinition, Restriction parent) { + public UnaryLogicalRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); } From 8569a9828e25ab99b700745596f6a293cfe11d26 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 28 Nov 2015 21:00:39 +0100 Subject: [PATCH 023/116] Preliminary support for "@" and ".." in repo queries, repo tests passing. --- .../midpoint/prism/schema/SchemaRegistry.java | 4 +- .../repo/sql/QueryInterpreter2Test.java | 117 ++++++++- .../midpoint/repo/sql/data/Marker.java | 25 ++ .../common/RAccessCertificationCampaign.java | 2 +- .../container/RAccessCertificationCase.java | 3 +- .../sql/query/definition/OwnerGetter.java | 39 +++ ...earchResult.java => DataSearchResult.java} | 23 +- .../sql/query2/InterpretationContext.java | 6 +- .../repo/sql/query2/InterpreterHelper.java | 73 +++--- ...esult.java => ProperDataSearchResult.java} | 13 +- .../sql/query2/QueryDefinitionRegistry2.java | 82 +++--- .../repo/sql/query2/QueryInterpreter2.java | 46 ++-- .../definition/ClassDefinitionParser.java | 117 ++++++--- .../definition/CollectionSpecification.java | 7 - .../sql/query2/definition/DefinitionPath.java | 10 +- .../query2/definition/JpaAnyDefinition.java | 22 +- .../definition/JpaDataNodeDefinition.java | 121 +++++++++ .../sql/query2/definition/JpaDefinition.java | 170 ------------ .../JpaEntityContentDefinition.java | 171 ------------ .../definition/JpaEntityDefinition.java | 245 +++++++++++++++++- .../definition/JpaEntityItemDefinition.java | 93 ------- .../JpaEntityPointerDefinition.java | 69 +++++ .../query2/definition/JpaItemDefinition.java | 86 ------ .../query2/definition/JpaLinkDefinition.java | 141 ++++++++++ .../definition/JpaPropertyDefinition.java | 36 +-- .../definition/JpaReferenceDefinition.java | 60 ++--- .../definition/JpaRootEntityDefinition.java | 77 ------ ...tor.java => LinkDefinitionComparator.java} | 19 +- .../definition/VirtualAnyDefinition.java | 12 +- .../repo/sql/query2/hqm/HibernateQuery.java | 12 +- .../sql/query2/hqm/RootHibernateQuery.java | 5 +- .../hqm/condition/HibernateSubquery.java | 4 +- .../restriction/AnyPropertyRestriction.java | 1 - .../restriction/ItemValueRestriction.java | 68 ----- .../restriction/NaryLogicalRestriction.java | 3 +- .../restriction/PropertyRestriction.java | 107 +++++++- .../restriction/ReferenceRestriction.java | 25 +- .../sql/query2/restriction/Restriction.java | 3 +- .../query2/restriction/TypeRestriction.java | 1 - .../restriction/UnaryLogicalRestriction.java | 1 - 40 files changed, 1140 insertions(+), 979 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/Marker.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerGetter.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{DefinitionSearchResult.java => DataSearchResult.java} (56%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ProperDefinitionSearchResult.java => ProperDataSearchResult.java} (63%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{DefinitionComparator.java => LinkDefinitionComparator.java} (63%) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java index f50071720b0..a59e1b553db 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/SchemaRegistry.java @@ -621,7 +621,9 @@ public QName qualifyTypeName(QName typeName) throws SchemaException { } public ComplexTypeDefinition determineParentDefinition(ComplexTypeDefinition complexTypeDefinition, ItemPath rest) { - ComplexTypeDefinition def = findComplexTypeDefinition(new QName("ObjectType")); // FIXME BRUTAL HACK + ComplexTypeDefinition def = findComplexTypeDefinition(new QName( + "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "ObjectType")); // FIXME BRUTAL HACK if (def == null) { throw new IllegalStateException("Couldn't find definition for parent for " + complexTypeDefinition.getTypeName() + ", path=" + rest); } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 05ded6ce90e..2a76667fd55 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -43,6 +43,7 @@ import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.schema.PrismSchema; import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; @@ -2492,7 +2493,7 @@ public void test750DereferenceLink() throws Exception { try { /* - * ### UserType: link/name contains 'test.com' + * ### UserType: linkRef/@/name contains 'test.com' */ ObjectFilter filter = SubstringFilter.createSubstring( @@ -2501,7 +2502,119 @@ public void test750DereferenceLink() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, UserType.class, query); -// assertEqualsIgnoreWhitespace(expected, real); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.linkRef l\n" + + " left join l.target t\n" + + "where\n" + + " (\n" + + " t.name.orig like :orig and\n" + + " t.name.norm like :norm\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test752DereferenceLinkedResourceName() throws Exception { + Session session = open(); + + try { + /* + * ### UserType: linkRef/@/resourceRef/@/name contains 'CSV' (norm) + */ + + ObjectFilter filter = SubstringFilter.createSubstring( + new ItemPath(UserType.F_LINK_REF, PrismConstants.T_OBJECT_REFERENCE, + ShadowType.F_RESOURCE_REF, PrismConstants.T_OBJECT_REFERENCE, + ShadowType.F_NAME), + UserType.class, prismContext, PolyStringNormMatchingRule.NAME, "CSV"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.linkRef l\n" + + " left join l.target t\n" + + " left join t.resourceRef.target t2\n" + + "where\n" + + " t2.name.norm like :norm\n"; + assertEqualsIgnoreWhitespace(expected, real); + + } finally { + close(session); + } + } + + @Test(expectedExceptions = IllegalStateException.class) // at this time + public void test760DereferenceAssignedRoleType() throws Exception { + Session session = open(); + + try { + /* + * This fails, as prism nor query interpreter expect that targetRef is RoleType/RRole. + * Prism should implement something like "searching for proper root" when dereferencing "@". + * QI should implement the proper root search not only at the query root, but always after a "@". + * + * ### UserType: assignment/targetRef/@/roleType + */ + + ObjectFilter filter = EqualFilter.createEqual( + new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_TARGET_REF, PrismConstants.T_OBJECT_REFERENCE, RoleType.F_ROLE_TYPE), + UserType.class, prismContext, "type1"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String real = getInterpretedQuery2(session, UserType.class, query); + + } finally { + close(session); + } + } + + @Test + public void test770CaseParentFilter() throws Exception { + Session session = open(); + + try { + /* + * ### AccessCertificationCaseType: Equal(../name, 'Campaign 1') + */ + + ObjectFilter filter = EqualFilter.createEqual( + new ItemPath(PrismConstants.T_PARENT, ObjectType.F_NAME), + AccessCertificationCaseType.class, prismContext, "Campaign 1"); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.owner o\n" + + "where\n" + + " (\n" + + " o.name.orig = :orig and\n" + + " o.name.norm = :norm\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/Marker.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/Marker.java new file mode 100644 index 00000000000..98d83c8c09c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/Marker.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data; + +/** + * Just to mark the "data" package. + * + * @author mederly + */ +public class Marker { +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index fb661447e46..49875deb471 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -80,7 +80,7 @@ public void setDefinitionRef(REmbeddedReference definitionRef) { @Cascade({org.hibernate.annotations.CascadeType.ALL}) public Set getCases() { if (cases == null) { - cases = new HashSet(); + cases = new HashSet<>(); } return cases; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index d1eef42d771..35b7ccd7491 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -25,6 +25,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerGetter; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -104,7 +105,7 @@ public RAccessCertificationCase(RObject owner) { @org.hibernate.annotations.ForeignKey(name = "fk_ac_case_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) - @NotQueryable + @OwnerGetter(ownerClass = RAccessCertificationCampaign.class) public RObject getOwner() { return owner; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerGetter.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerGetter.java new file mode 100644 index 00000000000..725568f38bb --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerGetter.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query.definition; + +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Denotes method that is used to access the container parent. E.g. AccessCertificationCase -> AccessCertificationCampaign. + * + * @author lazyman + * @author mederly + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface OwnerGetter { + + Class ownerClass(); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DataSearchResult.java similarity index 56% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DataSearchResult.java index 48a2cf273b8..b62ce024160 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DataSearchResult.java @@ -17,24 +17,25 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import org.apache.commons.lang.Validate; /** * @author mederly */ -public class DefinitionSearchResult { - private T itemDefinition; // definition of the item itself - private ItemPath remainder; // what has remained unresolved of the original search path +public class DataSearchResult { + private JpaLinkDefinition linkDefinition; + private ItemPath remainder; // what has remained unresolved of the original search path - public DefinitionSearchResult(T itemDefinition, ItemPath remainder) { - Validate.notNull(itemDefinition, "itemDefinition"); - this.itemDefinition = itemDefinition; + public DataSearchResult(JpaLinkDefinition linkDefinition, ItemPath remainder) { + Validate.notNull(linkDefinition, "linkDefinition"); + this.linkDefinition = linkDefinition; this.remainder = remainder; } - public T getItemDefinition() { - return itemDefinition; + public JpaLinkDefinition getLinkDefinition() { + return linkDefinition; } public ItemPath getRemainder() { @@ -44,4 +45,8 @@ public ItemPath getRemainder() { public boolean isComplete() { return ItemPath.isNullOrEmpty(remainder); } + + public T getTargetDefinition() { + return linkDefinition.getTargetDefinition(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index cb2852d0542..39321020504 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -19,7 +19,7 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -50,7 +50,7 @@ public class InterpretationContext { * by the search operation, or the one that was refined from abstract types (ObjectType, AbstractRoleType, ...) * in the process of restriction construction. */ - private JpaRootEntityDefinition rootEntityDefinition; + private JpaEntityDefinition rootEntityDefinition; public InterpretationContext(QueryInterpreter2 interpreter, Class type, PrismContext prismContext, Session session) throws QueryException { @@ -100,7 +100,7 @@ public InterpreterHelper getHelper() { return helper; } - public JpaRootEntityDefinition getRootEntityDefinition() { + public JpaEntityDefinition getRootEntityDefinition() { return rootEntityDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java index e24c11b32fd..5aaa220a8ca 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java @@ -22,13 +22,11 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; @@ -63,7 +61,7 @@ public InterpreterHelper(InterpretationContext interpretationContext) { // returns property path that can be used to access the item values public String prepareJoins(ItemPath relativePath, String currentHqlPath, JpaEntityDefinition baseEntityDefinition) throws QueryException { - LOGGER.trace("Updating query context based on path {}", relativePath); + LOGGER.trace("Updating query context based on path '{}'", relativePath); /** * We have to do something like this - examples: @@ -77,49 +75,52 @@ public String prepareJoins(ItemPath relativePath, String currentHqlPath, JpaEnti * - assignment.target.longs -> "left join u.assignments a (...) left join a.target t left join t.longs (...)" */ - JpaDefinition currentDefinition = (JpaDefinition) baseEntityDefinition; + JpaDataNodeDefinition currentDefinition = baseEntityDefinition; ItemPath itemPathRemainder = relativePath; while (!ItemPath.isNullOrEmpty(itemPathRemainder)) { - DefinitionSearchResult result = currentDefinition.nextDefinition(itemPathRemainder); - LOGGER.trace("nextDefinition on {} returned {}", itemPathRemainder, result != null ? result.getItemDefinition() : "(null)"); + LOGGER.trace("currentDefinition = '{}', current HQL path = '{}', itemPathRemainder = '{}'", currentDefinition, currentHqlPath, itemPathRemainder); + DataSearchResult result = currentDefinition.nextLinkDefinition(itemPathRemainder); + LOGGER.trace("nextLinkDefinition on '{}' returned '{}'", itemPathRemainder, result != null ? result.getLinkDefinition() : "(null)"); if (result == null) { // sorry we failed (however, this should be caught before -> so IllegalStateException) throw new IllegalStateException("Couldn't find " + itemPathRemainder + " in " + currentDefinition); } - JpaItemDefinition itemDefinition = result.getItemDefinition(); + JpaLinkDefinition linkDefinition = result.getLinkDefinition(); + JpaDataNodeDefinition nextNodeDefinition = linkDefinition.getTargetDefinition(); - if (itemDefinition instanceof JpaAnyDefinition) { - JpaAnyDefinition anyDefinition = (JpaAnyDefinition) itemDefinition; - if (anyDefinition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes + if (nextNodeDefinition instanceof JpaAnyDefinition) { + JpaAnyDefinition anyDefinition = (JpaAnyDefinition) nextNodeDefinition; + if (linkDefinition.getJpaName() != null) { // there are "invisible" Any definitions - object extension and shadow attributes + currentHqlPath = addJoin(linkDefinition, currentHqlPath); LOGGER.trace("Adding join for '{}' to context", anyDefinition); - currentHqlPath = addJoin(anyDefinition, currentHqlPath); } break; // we're done - } else if (itemDefinition instanceof JpaEntityItemDefinition) { - JpaEntityItemDefinition entityDef = (JpaEntityItemDefinition) itemDefinition; - if (!entityDef.isEmbedded() || entityDef.isMultivalued()) { - LOGGER.trace("Adding join for '{}' to context", entityDef); - currentHqlPath = addJoin(entityDef, currentHqlPath); + } else if (nextNodeDefinition instanceof JpaEntityDefinition) { + if (!linkDefinition.isEmbedded() || linkDefinition.isMultivalued()) { + LOGGER.trace("Adding join for '{}' to context", linkDefinition); + currentHqlPath = addJoin(linkDefinition, currentHqlPath); } else { - currentHqlPath += "." + entityDef.getJpaName(); + currentHqlPath += "." + linkDefinition.getJpaName(); } - } else if (itemDefinition instanceof JpaPropertyDefinition || itemDefinition instanceof JpaReferenceDefinition) { - if (itemDefinition.isMultivalued()) { - LOGGER.trace("Adding join for '{}' to context", itemDefinition); - currentHqlPath = addJoin(itemDefinition, currentHqlPath); + } else if (nextNodeDefinition instanceof JpaPropertyDefinition || nextNodeDefinition instanceof JpaReferenceDefinition) { + if (linkDefinition.isMultivalued()) { + LOGGER.trace("Adding join for '{}' to context", linkDefinition); + currentHqlPath = addJoin(linkDefinition, currentHqlPath); + } else { + currentHqlPath += "." + linkDefinition.getJpaName(); } } else { - throw new QueryException("Not implemented yet: " + itemDefinition); + throw new QueryException("Not implemented yet: " + linkDefinition); } itemPathRemainder = result.getRemainder(); - currentDefinition = itemDefinition; + currentDefinition = nextNodeDefinition; } - LOGGER.trace("prepareJoins({}) returning currentHqlPath of {}", relativePath, currentHqlPath); + LOGGER.trace("prepareJoins({}) returning currentHqlPath of '{}'", relativePath, currentHqlPath); return currentHqlPath; } - private String addJoin(JpaItemDefinition joinedItemDefinition, String currentHqlPath) throws QueryException { + private String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String joinedItemJpaName = joinedItemDefinition.getJpaName(); String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; @@ -196,17 +197,17 @@ public String addJoinAny(String currentHqlPath, String anyAssociationName, QName * @param clazz Kind of definition to be looked for * @return Entity type definition + item definition, or null if nothing was found */ - public - ProperDefinitionSearchResult findProperDefinition(JpaEntityDefinition baseEntityDefinition, - ItemPath path, Class clazz) throws QueryException { + public + ProperDataSearchResult findProperDataDefinition(JpaEntityDefinition baseEntityDefinition, + ItemPath path, Class clazz) throws QueryException { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - ProperDefinitionSearchResult candidateResult = null; + ProperDataSearchResult candidateResult = null; for (JpaEntityDefinition entityDefinition : findPossibleBaseEntities(baseEntityDefinition, registry)) { - DefinitionSearchResult result = entityDefinition.findDefinition(path, clazz); + DataSearchResult result = entityDefinition.findDataNodeDefinition(path, clazz); if (result != null) { if (candidateResult == null) { - candidateResult = new ProperDefinitionSearchResult<>(entityDefinition, result); + candidateResult = new ProperDataSearchResult<>(entityDefinition, result); } else { // Check for compatibility. As entities are presented from the more abstract to less abstract, // there is no possibility of false alarm. @@ -218,7 +219,7 @@ ProperDefinitionSearchResult findProperDefinition(JpaEntityDefinition baseEnt } } } - LOGGER.trace("findProperDefinition: base={}, path={}, class={} -- returning {}", + LOGGER.trace("findProperDataDefinition: base='{}', path='{}', class={} -- returning '{}'", baseEntityDefinition, path, clazz.getSimpleName(), candidateResult); return candidateResult; } @@ -235,9 +236,9 @@ private List findPossibleBaseEntities(JpaEntityDefinition e /** * Given existing entity definition and a request for narrowing it, tries to find refined definition. */ - public JpaRootEntityDefinition findRestrictedEntityDefinition(JpaEntityDefinition baseEntityDefinition, QName specificTypeName) throws QueryException { + public JpaEntityDefinition findRestrictedEntityDefinition(JpaEntityDefinition baseEntityDefinition, QName specificTypeName) throws QueryException { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); - JpaRootEntityDefinition specificEntityDefinition = registry.findEntityDefinition(specificTypeName); + JpaEntityDefinition specificEntityDefinition = registry.findEntityDefinition(specificTypeName); if (!baseEntityDefinition.isAssignableFrom(specificEntityDefinition)) { throw new QueryException("Entity " + baseEntityDefinition + " cannot be restricted to " + specificEntityDefinition); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDataSearchResult.java similarity index 63% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDataSearchResult.java index 25db321b1ac..ec3a19f17cd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDefinitionSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDataSearchResult.java @@ -16,22 +16,19 @@ package com.evolveum.midpoint.repo.sql.query2; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; import org.apache.commons.lang.Validate; /** * @author mederly */ -public class ProperDefinitionSearchResult extends DefinitionSearchResult { +public class ProperDataSearchResult extends DataSearchResult { JpaEntityDefinition entityDefinition; // entity in which the item was found - public ProperDefinitionSearchResult(JpaEntityDefinition entityDefinition, DefinitionSearchResult result) { - super(result.getItemDefinition(), result.getRemainder()); + public ProperDataSearchResult(JpaEntityDefinition entityDefinition, DataSearchResult result) { + super(result.getLinkDefinition(), result.getRemainder()); Validate.notNull(entityDefinition, "entityDefinition"); this.entityDefinition = entityDefinition; } @@ -43,6 +40,6 @@ public JpaEntityDefinition getEntityDefinition() { @Override public String toString() { return "ProperDefinitionSearchResult{" + - "entity=" + entityDefinition + ", item=" + getItemDefinition() + ", remainder=" + getRemainder() + "} "; + "entity=" + entityDefinition + ", item=" + getLinkDefinition() + ", remainder=" + getRemainder() + "} "; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java index 78522517d9c..a614acc8e1c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -19,16 +19,13 @@ import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.ClassDefinitionParser; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityPointerDefinition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.util.DebugDumpable; @@ -53,7 +50,7 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { private static final Trace LOGGER = TraceManager.getTrace(QueryDefinitionRegistry2.class); - private static final Map definitions; + private static final Map definitions; private static QueryDefinitionRegistry2 registry; @@ -61,8 +58,8 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { LOGGER.trace("Initializing query definition registry."); ClassDefinitionParser classDefinitionParser = new ClassDefinitionParser(); - final Map map = new HashMap<>(); - final Map, JpaRootEntityDefinition> definitionsByClass = new HashMap<>(); + final Map map = new HashMap<>(); + final Map, JpaEntityDefinition> definitionsByClass = new HashMap<>(); Collection types = ClassMapper.getKnownTypes(); for (RObjectType type : types) { @@ -71,7 +68,7 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { continue; } - JpaRootEntityDefinition definition = classDefinitionParser.parseRootClass(clazz); + JpaEntityDefinition definition = classDefinitionParser.parseRootClass(clazz); if (definition == null) { continue; } @@ -82,37 +79,49 @@ public class QueryDefinitionRegistry2 implements DebugDumpable { } // TODO fix this hack - JpaRootEntityDefinition caseDefinition = classDefinitionParser.parseRootClass(RAccessCertificationCase.class); + JpaEntityDefinition caseDefinition = classDefinitionParser.parseRootClass(RAccessCertificationCase.class); map.put(AccessCertificationCaseType.COMPLEX_TYPE, caseDefinition); // link parents (maybe not needed at all, we'll see) and referenced entity definitions - for (final JpaRootEntityDefinition definition : map.values()) { + // sort definitions + for (final JpaEntityDefinition definition : map.values()) { Visitor resolutionVisitor = new Visitor() { @Override public void visit(Visitable visitable) { - if (visitable instanceof JpaRootEntityDefinition) { - JpaRootEntityDefinition entityDef = ((JpaRootEntityDefinition) visitable); + if (visitable instanceof JpaEntityDefinition) { + JpaEntityDefinition entityDef = ((JpaEntityDefinition) visitable); Class superclass = entityDef.getJpaClass().getSuperclass(); - if (!RObject.class.isAssignableFrom(superclass)) { + if (superclass == null || !RObject.class.isAssignableFrom(superclass)) { return; } - JpaRootEntityDefinition superclassDefinition = definitionsByClass.get(superclass); + JpaEntityDefinition superclassDefinition = definitionsByClass.get(superclass); if (superclassDefinition == null) { throw new IllegalStateException("No definition for superclass " + superclass + " of " + entityDef); } - entityDef.getContent().setSuperclassDefinition(superclassDefinition); - } else if (visitable instanceof JpaReferenceDefinition) { - JpaReferenceDefinition entRefDef = ((JpaReferenceDefinition) visitable); - Class referencedEntityJpaClass = entRefDef.getReferencedEntityJpaClass(); - JpaRootEntityDefinition realEntDef = definitionsByClass.get(referencedEntityJpaClass); + entityDef.setSuperclassDefinition(superclassDefinition); + } else if (visitable instanceof JpaEntityPointerDefinition) { + JpaEntityPointerDefinition entPtrDef = ((JpaEntityPointerDefinition) visitable); + Class referencedEntityJpaClass = entPtrDef.getJpaClass(); + JpaEntityDefinition realEntDef = definitionsByClass.get(referencedEntityJpaClass); if (realEntDef == null) { throw new IllegalStateException("Couldn't find entity definition for " + referencedEntityJpaClass); } - entRefDef.setReferencedEntityDefinition(realEntDef); + entPtrDef.setResolvedEntityDefinition(realEntDef); } } }; definition.accept(resolutionVisitor); + + Visitor sortingVisitor = new Visitor() { + @Override + public void visit(Visitable visitable) { + if (visitable instanceof JpaEntityDefinition) { + JpaEntityDefinition entityDef = ((JpaEntityDefinition) visitable); + entityDef.sortDefinitions(); + } + } + }; + definition.accept(sortingVisitor); } definitions = Collections.unmodifiableMap(map); @@ -141,18 +150,18 @@ public String debugDump() { public String debugDump(int indent) { StringBuilder builder = new StringBuilder(); DebugUtil.indentDebugDump(builder, indent); - Collection defCollection = definitions.values(); - for (JpaRootEntityDefinition definition : defCollection) { - builder.append(definition.debugDump()).append('\n'); + Collection defCollection = definitions.values(); + for (JpaEntityDefinition definition : defCollection) { + builder.append(definition.debugDump(indent)).append('\n'); } return builder.toString(); } - public JpaRootEntityDefinition findEntityDefinition(QName typeName) { + public JpaEntityDefinition findEntityDefinition(QName typeName) { Validate.notNull(typeName, "Type name must not be null."); - JpaRootEntityDefinition def = definitions.get(typeName); + JpaEntityDefinition def = definitions.get(typeName); if (def == null) { throw new IllegalStateException("Type " + typeName + " couldn't be found in type registry"); } @@ -160,7 +169,7 @@ public JpaRootEntityDefinition findEntityDefinition(QName typeName) { } // always returns non-null value - public JpaRootEntityDefinition findEntityDefinition(Class type) throws QueryException { + public JpaEntityDefinition findEntityDefinition(Class type) throws QueryException { Validate.notNull(type, "Type must not be null."); return findEntityDefinition(getQNameForType(type)); } @@ -175,31 +184,24 @@ public QName getQNameForType(Class type) throws Que throw new QueryException("Unsupported type " + type); } - public DefinitionSearchResult findDefinition(Class type, ItemPath path, Class definitionType) throws QueryException { - Validate.notNull(type, "Type must not be null."); - Validate.notNull(definitionType, "Definition type must not be null."); - JpaRootEntityDefinition entityDef = findEntityDefinition(type); - return entityDef.findDefinition(path, definitionType); - } - /** * Returns possible "children" of a given definition. * More abstract classes are listed first. */ - public List getChildrenOf(JpaEntityDefinition entityDefinition) { - List retval = new ArrayList<>(); - List children = getDirectChildrenOf(entityDefinition); - for (JpaRootEntityDefinition child : children) { + public List getChildrenOf(JpaEntityDefinition entityDefinition) { + List retval = new ArrayList<>(); + List children = getDirectChildrenOf(entityDefinition); + for (JpaEntityDefinition child : children) { retval.add(child); retval.addAll(getChildrenOf(child)); } return retval; } - private List getDirectChildrenOf(JpaEntityDefinition parentDefinition) { + private List getDirectChildrenOf(JpaEntityDefinition parentDefinition) { Class parentClass = parentDefinition.getJpaClass(); - List retval = new ArrayList<>(); - for (JpaRootEntityDefinition definition : definitions.values()) { + List retval = new ArrayList<>(); + for (JpaEntityDefinition definition : definitions.values()) { if (parentClass.equals(definition.getJpaClass().getSuperclass())) { retval.add(definition); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index 2111ea65103..f1d9a33cf72 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -40,13 +40,10 @@ import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.ProjectionElement; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -188,8 +185,8 @@ public Condition interpretFilter(InterpretationContext context, ObjectFilter fil private Restriction findAndCreateRestriction(T filter, InterpretationContext context, Restriction parent) throws QueryException { - Validate.notNull(filter); - Validate.notNull(context); + Validate.notNull(filter, "filter"); + Validate.notNull(context, "context"); LOGGER.trace("Determining restriction for filter {}", filter); @@ -229,32 +226,32 @@ Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext con } else if (filter instanceof ExistsFilter) { ExistsFilter existsFilter = (ExistsFilter) filter; ItemPath path = existsFilter.getFullPath(); - ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, JpaEntityItemDefinition.class); + ProperDataSearchResult searchResult = helper.findProperDataDefinition(baseEntityDefinition, path, JpaEntityDefinition.class); if (searchResult == null) { throw new QueryException("Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity"); } - return new ExistsRestriction(context, existsFilter, searchResult.getEntityDefinition(), parent, searchResult.getItemDefinition()); + return new ExistsRestriction(context, existsFilter, searchResult.getEntityDefinition(), parent, searchResult.getTargetDefinition()); } else if (filter instanceof RefFilter) { RefFilter refFilter = (RefFilter) filter; ItemPath path = refFilter.getFullPath(); - ProperDefinitionSearchResult searchResult = helper.findProperDefinition(baseEntityDefinition, path, JpaReferenceDefinition.class); + ProperDataSearchResult searchResult = helper.findProperDataDefinition(baseEntityDefinition, path, JpaReferenceDefinition.class); if (searchResult == null) { throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a reference item"); } return new ReferenceRestriction(context, refFilter, searchResult.getEntityDefinition(), - parent, searchResult.getItemDefinition()); + parent, searchResult.getLinkDefinition()); } else if (filter instanceof ValueFilter) { ValueFilter valFilter = (ValueFilter) filter; ItemPath path = valFilter.getFullPath(); - ProperDefinitionSearchResult propDefRes = helper.findProperDefinition(baseEntityDefinition, path, JpaPropertyDefinition.class); + ProperDataSearchResult propDefRes = helper.findProperDataDefinition(baseEntityDefinition, path, JpaPropertyDefinition.class); if (propDefRes != null) { - return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getItemDefinition()); + return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getLinkDefinition()); } - ProperDefinitionSearchResult anyDefRes = helper.findProperDefinition(baseEntityDefinition, path, JpaAnyDefinition.class); + ProperDataSearchResult anyDefRes = helper.findProperDataDefinition(baseEntityDefinition, path, JpaAnyDefinition.class); if (anyDefRes != null) { if (ItemPath.containsSingleNameSegment(anyDefRes.getRemainder())) { - return new AnyPropertyRestriction(context, valFilter, anyDefRes.getEntityDefinition(), parent, anyDefRes.getItemDefinition()); + return new AnyPropertyRestriction(context, valFilter, anyDefRes.getEntityDefinition(), parent, anyDefRes.getTargetDefinition()); } else { throw new QueryException("Unsupported any-targeted query: should contain single item name to be resolved in the 'any' container but contains '" + anyDefRes.getRemainder() + "' instead"); @@ -322,27 +319,28 @@ public void updatePagingAndSorting(InterpretationConte } } - ProperDefinitionSearchResult result = context.getHelper().findProperDefinition( - context.getRootEntityDefinition(), orderByPath, JpaItemDefinition.class); + ProperDataSearchResult result = context.getHelper().findProperDataDefinition( + context.getRootEntityDefinition(), orderByPath, JpaDataNodeDefinition.class); if (result == null) { throw new QueryException("Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it."); - } else if (result.getItemDefinition() instanceof JpaAnyDefinition) { + } + JpaDataNodeDefinition targetDefinition = result.getLinkDefinition().getTargetDefinition(); + if (targetDefinition instanceof JpaAnyDefinition) { throw new QueryException("Sorting based on extension item or attribute is not supported yet: " + orderByPath); - } else if (result.getItemDefinition() instanceof JpaReferenceDefinition) { + } else if (targetDefinition instanceof JpaReferenceDefinition) { throw new QueryException("Sorting based on reference is not supported: " + orderByPath); - } else if (result.getItemDefinition().isMultivalued()) { + } else if (result.getLinkDefinition().isMultivalued()) { throw new QueryException("Sorting based on multi-valued item is not supported: " + orderByPath); - } else if (result.getItemDefinition() instanceof JpaEntityItemDefinition) { + } else if (targetDefinition instanceof JpaEntityDefinition) { throw new QueryException("Sorting based on entity is not supported: " + orderByPath); - } else if (!(result.getItemDefinition() instanceof JpaPropertyDefinition)) { + } else if (!(targetDefinition instanceof JpaPropertyDefinition)) { throw new IllegalStateException("Unknown item definition type: " + result.getClass()); } JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition(); - JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) result.getItemDefinition(); - String hqlPropertyPath = context.getHelper().prepareJoins(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition) - + "." + orderByDefinition.getJpaName(); + JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) targetDefinition; + String hqlPropertyPath = context.getHelper().prepareJoins(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition); if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 92ea20e82f8..050022d1b3d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -16,15 +16,21 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.path.ParentPathSegment; +import com.evolveum.midpoint.repo.sql.data.Marker; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.definition.Any; import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerGetter; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; +import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.apache.commons.lang.StringUtils; @@ -51,15 +57,14 @@ public class ClassDefinitionParser { private static final Trace LOGGER = TraceManager.getTrace(ClassDefinitionParser.class); - public JpaRootEntityDefinition parseRootClass(Class jpaClass) { - JpaEntityContentDefinition content = parseClass(jpaClass); - JpaRootEntityDefinition rootEntityDefinition = new JpaRootEntityDefinition(jpaClass, content); - return rootEntityDefinition; + public JpaEntityDefinition parseRootClass(Class jpaClass) { + return parseClass(jpaClass); } - private JpaEntityContentDefinition parseClass(Class jpaClass) { + private JpaEntityDefinition parseClass(Class jpaClass) { - JpaEntityContentDefinition entity = new JpaEntityContentDefinition(); + Class jaxbClass = getJaxbClassForEntity(jpaClass); + JpaEntityDefinition entity = new JpaEntityDefinition(jpaClass, jaxbClass); LOGGER.trace("### {}", entity); addVirtualDefinitions(jpaClass, entity); @@ -79,13 +84,22 @@ private JpaEntityContentDefinition parseClass(Class jpaClass) { } LOGGER.trace("# {}", method); - JpaItemDefinition jpaItemDefinition = parseMethod(method); - entity.addDefinition(jpaItemDefinition); + + JpaLinkDefinition linkDefinition; + OwnerGetter ownerGetter = method.getAnnotation(OwnerGetter.class); + if (ownerGetter != null) { + String jpaName = getJpaName(method); + JpaDataNodeDefinition nodeDefinition = new JpaEntityPointerDefinition(ownerGetter.ownerClass()); + linkDefinition = new JpaLinkDefinition(new ParentPathSegment(), jpaName, null, nodeDefinition); + } else { + linkDefinition = parseMethod(method); + } + entity.addDefinition(linkDefinition); } return entity; } - private JpaItemDefinition parseMethod(Method method) { + private JpaLinkDefinition parseMethod(Method method) { CollectionSpecification collectionSpecification; // non-null if return type is Set, null if it's X Type returnedContentType; // X in return type, which is either X or Set if (Set.class.isAssignableFrom(method.getReturnType())) { @@ -110,11 +124,12 @@ private JpaItemDefinition parseMethod(Method method) { throw new IllegalStateException("Collection within collection is not supported: method=" + method); } - JpaItemDefinition definition; - Any any = (Any) jpaClass.getAnnotation(Any.class); + JpaLinkDefinition linkDefinition; + Any any = method.getAnnotation(Any.class); if (any != null) { - jaxbName = new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()); - definition = new JpaAnyDefinition(jaxbName, jpaName, jpaClass); + JpaAnyDefinition targetDefinition = new JpaAnyDefinition(jpaClass); + QName jaxbNameForAny = new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()); + linkDefinition = new JpaLinkDefinition<>(jaxbNameForAny, jpaName, collectionSpecification, targetDefinition); } else if (ObjectReference.class.isAssignableFrom(jpaClass)) { boolean embedded = method.isAnnotationPresent(Embedded.class); // computing referenced entity type from returned content type like RObjectReference or REmbeddedReference @@ -124,19 +139,22 @@ private JpaItemDefinition parseMethod(Method method) { } else { referencedJpaClass = RObject.class; } - definition = new JpaReferenceDefinition(jaxbName, jpaName, collectionSpecification, jpaClass, referencedJpaClass, embedded); + JpaReferenceDefinition targetDefinition = new JpaReferenceDefinition(jpaClass, referencedJpaClass); + linkDefinition = new JpaLinkDefinition<>(jaxbName, jpaName, collectionSpecification, embedded, targetDefinition); } else if (isEntity(jpaClass)) { - JpaEntityContentDefinition content = parseClass(jpaClass); + JpaEntityDefinition content = parseClass(jpaClass); boolean embedded = method.isAnnotationPresent(Embedded.class) || jpaClass.isAnnotationPresent(Embeddable.class); - definition = new JpaEntityItemDefinition(jaxbName, jpaName, collectionSpecification, jpaClass, content, embedded); + linkDefinition = new JpaLinkDefinition(jaxbName, jpaName, collectionSpecification, embedded, content); } else { boolean lob = method.isAnnotationPresent(Lob.class); boolean enumerated = method.isAnnotationPresent(Enumerated.class); //todo implement also lookup for @Table indexes boolean indexed = method.isAnnotationPresent(Index.class); - definition = new JpaPropertyDefinition(jaxbName, jpaName, collectionSpecification, jpaClass, lob, enumerated, indexed); + Class jaxbClass = getJaxbClass(method, jpaClass); + JpaPropertyDefinition propertyDefinition = new JpaPropertyDefinition(jpaClass, jaxbClass, lob, enumerated, indexed); + linkDefinition = new JpaLinkDefinition(jaxbName, jpaName, collectionSpecification, false, propertyDefinition); } - return definition; + return linkDefinition; } private Class getClass(Type type) { @@ -149,7 +167,7 @@ private Class getClass(Type type) { } } - private void addVirtualDefinitions(Class jpaClass, JpaEntityContentDefinition entityDef) { + private void addVirtualDefinitions(Class jpaClass, JpaEntityDefinition entityDef) { addVirtualDefinitionsForClass(jpaClass, entityDef); while ((jpaClass = jpaClass.getSuperclass()) != null) { @@ -157,7 +175,7 @@ private void addVirtualDefinitions(Class jpaClass, JpaEntityContentDefinition en } } - private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityContentDefinition entityDef) { + private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityDefinition entityDef) { if (!jpaClass.isAnnotationPresent(QueryEntity.class)) { return; } @@ -165,10 +183,10 @@ private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityContentDefin QueryEntity qEntity = (QueryEntity) jpaClass.getAnnotation(QueryEntity.class); for (VirtualAny any : qEntity.anyElements()) { - VirtualAnyDefinition def = new VirtualAnyDefinition( - new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()), - any.ownerType()); - entityDef.addDefinition(def); + QName jaxbName = new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()); + VirtualAnyDefinition def = new VirtualAnyDefinition(any.ownerType()); + JpaLinkDefinition linkDefinition = new JpaLinkDefinition(jaxbName, null, null, def); + entityDef.addDefinition(linkDefinition); } for (VirtualCollection collection : qEntity.collections()) { @@ -176,10 +194,12 @@ private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityContentDefin VirtualCollectionSpecification colSpec = new VirtualCollectionSpecification(collection.additionalParams()); QName jaxbName = createQName(collection.jaxbName()); String jpaName = collection.jpaName(); - JpaEntityContentDefinition content = parseClass(collection.jpaType()); - JpaEntityItemDefinition definition = new JpaEntityItemDefinition(jaxbName, jpaName, colSpec, jpaClass, content, false); - entityDef.addDefinition(definition); + JpaEntityDefinition content = parseClass(collection.collectionType()); + JpaLinkDefinition linkDefinition = new JpaLinkDefinition(jaxbName, jpaName, colSpec, content); + entityDef.addDefinition(linkDefinition); } + + // TODO virtual entity collections (for metadata and construction) } private QName createQName(JaxbName name) { @@ -203,19 +223,36 @@ private QName getJaxbName(Method method) { } } -// private Class getJaxbClass(Class clazz) { -// if (RObject.class.isAssignableFrom(clazz)) { -// ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(clazz); -// return objectType.getClassDefinition(); -// } -// -// if (clazz.getAnnotation(JaxbType.class) != null) { -// JaxbType type = (JaxbType) clazz.getAnnotation(JaxbType.class); -// return type.type(); -// } -// -// return clazz; -// } + // second parameter is just to optimize + private Class getJaxbClass(Method method, Class returnedClass) { + JaxbType annotation = (JaxbType) method.getAnnotation(JaxbType.class); + if (annotation != null) { + return annotation.type(); + } + Class classFromEntity = getJaxbClassForEntity(returnedClass); + if (classFromEntity != null) { + return classFromEntity; + } + Package returnedClassPkg = returnedClass.getPackage(); + Package dataObjectsPkg = Marker.class.getPackage(); + if (returnedClassPkg != null && returnedClassPkg.getName().startsWith(dataObjectsPkg.getName())) { + return null; + } else { + return returnedClass; // probably the JAXB value + } + } + + private Class getJaxbClassForEntity(Class clazz) { + if (RObject.class.isAssignableFrom(clazz)) { + ObjectTypes objectType = ClassMapper.getObjectTypeForHQLType(clazz); + return objectType.getClassDefinition(); + } + JaxbType annotation = (JaxbType) clazz.getAnnotation(JaxbType.class); + if (annotation != null) { + return annotation.type(); + } + return null; + } private String getJpaName(Method method) { String methodName = method.getName(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java index 34b6d7c44e5..e13801d425e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/CollectionSpecification.java @@ -16,13 +16,6 @@ package com.evolveum.midpoint.repo.sql.query2.definition; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.Holder; - -import javax.xml.namespace.QName; - /** * In current version this is just a marker class - there's nothing to be said about standard collections yet. * diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java index bb1852fe8c7..971c00a22ab 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java @@ -39,13 +39,13 @@ */ public class DefinitionPath { - private List definitions = new ArrayList<>(); + private List definitions = new ArrayList<>(); - public void add(JpaItemDefinition definition) { + public void add(JpaLinkDefinition definition) { definitions.add(definition); } - public List getDefinitions() { + public List getDefinitions() { return definitions; } @@ -53,7 +53,7 @@ public int size() { return definitions.size(); } - public JpaItemDefinition get(int i) { + public JpaLinkDefinition get(int i) { return definitions.get(i); } @@ -63,7 +63,7 @@ public String toString() { sb.append('['); boolean first = true; - for (JpaItemDefinition definition : definitions) { + for (JpaLinkDefinition definition : definitions) { if (first) { first = false; } else { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java index b79b5151643..4bcef663355 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java @@ -18,17 +18,15 @@ import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; - -import javax.xml.namespace.QName; +import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; /** * @author lazyman */ -public class JpaAnyDefinition extends JpaItemDefinition { +public class JpaAnyDefinition extends JpaDataNodeDefinition { - public JpaAnyDefinition(QName jaxbName, String jpaName, Class jpaClass) { - super(jaxbName, jpaName, null, jpaClass); // no collection specification for this kind of item + public JpaAnyDefinition(Class jpaClass) { + super(jpaClass, null); } @Override @@ -37,12 +35,8 @@ protected String getDebugDumpClassName() { } @Override - public DefinitionSearchResult nextDefinition(ItemPath path) { - // There is nothing we can do here. Return the definition itself, and - // the path as to be found within the appropriate Any container. - // Hoping the client will understand this and won't cycle while finding - // the definition. ;) - return new DefinitionSearchResult(this, path); + public DataSearchResult nextLinkDefinition(ItemPath path) { + throw new UnsupportedOperationException(); // TODO } @Override @@ -51,7 +45,7 @@ public void accept(Visitor visitor) { } @Override - protected void debugDumpExtended(StringBuilder sb, int indent) { - // nothing to put here + public String debugDump(int indent) { + return super.getShortInfo(); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java new file mode 100644 index 00000000000..ce176671720 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; + +/** + * Defines piece of JPA data - entity, property, reference, or "any" container. Used to convert ItemPath to HQL query, + * or, specifically, to a property path with left outer joins where appropriate. + * + * The conversion works like running DFA (deterministic finite automaton) where + * data definitions are states, and ItemPathSegments are alphabet symbols. + * + * In addition to recognize input words, this automaton produces HQL path and property joins. That's why + * each possible transition is labeled with (ItemPathSegment, JPA name, other transition data) tuple. + * ItemPathSegment is used to match the input word (path), while JPA name + other transition data, along + * with target state information (potentially) are used to generate HQL property path with appropriate join, + * if necessary. + * + * Note that some transitions may have empty JPA name - when the data is contained directly in owner entity + * (e.g. metadata, construction, object extension, shadow attributes). + * + * By other transition data we currently mean: collection specification, or "embedded" flag. + * + * Terminology: + * - state ~ data node (JpaDataNodeDefinition -> JpaEntityDefinition, JpaPropertyDefinition, ...) + * - transition ~ link node (JpaLinkDefinition) + * + * @author mederly + */ +public abstract class JpaDataNodeDefinition implements DebugDumpable, Visitable { + + private static final Trace LOGGER = TraceManager.getTrace(JpaDataNodeDefinition.class); + + /** + * JPA class - either "composite" (RObject, RUser, RAssignment, ...) or "primitive" (String, Integer, int, ...) + */ + private Class jpaClass; + + /** + * JAXB class - either "composite" (ObjectType, UserType, AssignmentType, ...) or "primitive" (String, Integer, int, ...) + * Null if not known. + */ + private Class jaxbClass; + + public JpaDataNodeDefinition(Class jpaClass, Class jaxbClass) { + Validate.notNull(jpaClass, "jpaClass"); + this.jpaClass = jpaClass; + this.jaxbClass = jaxbClass; + } + + public Class getJpaClass() { + return jpaClass; + } + + public String getJpaClassName() { + return jpaClass.getSimpleName(); + } + + public Class getJaxbClass() { + return jaxbClass; + } + + /** + * Tries to find "next step" in the translation process for a given ItemPath. + * Parts of the path that have no representation in the repository (e.g. metadata, + * construction) are skipped. + * + * @param path A path to be resolved. Always non-null and non-empty. Should produce at least one transition. + * @return + * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain + * and the unresolved remainder of the path. + * - If the search was not successful, returns null. + * + * Method is not supported on AnyDefinition! + */ + public abstract DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException; + + public String toString() { + return getShortInfo(); + } + + protected abstract String getDebugDumpClassName(); + + @Override + public String debugDump() { + return debugDump(0); + } + + public String getShortInfo() { + StringBuilder sb = new StringBuilder(); + sb.append(getDebugDumpClassName()).append(':').append(getJpaClassName()); + if (jaxbClass != null) { + sb.append(" (jaxb=").append(jaxbClass.getSimpleName()).append(")"); + } + return sb.toString(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java deleted file mode 100644 index 1f34519587a..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDefinition.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.Visitable; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import org.apache.commons.lang.Validate; - -import javax.xml.namespace.QName; - -/** - * Defines the content of item or standalone entity. - * - * @author mederly - */ -public abstract class JpaDefinition implements DebugDumpable, Visitable { - - private static final Trace LOGGER = TraceManager.getTrace(JpaDefinition.class); - - /** - * JPA class - either "composite" (RObject, RUser, RAssignment, ...) or "primitive" (String, Integer, int, ...) - */ - private Class jpaClass; - - public JpaDefinition(Class jpaClass) { - Validate.notNull(jpaClass, "jpaClass"); - this.jpaClass = jpaClass; - } - - public Class getJpaClass() { - return jpaClass; - } - - public String getJpaClassName() { - return jpaClass.getSimpleName(); - } - - /** - * Tries to find "next step" in the definition chain for a given ItemPath. - * Parts of the path that have no representation in the repository (e.g. metadata, - * construction) are simply skipped. - * - * @param path A path to be resolved. Always non-null and non-empty. - * @return - * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain - * and the unresolved remainder of the path. - * - If the search was not successful, returns null. - * - Note that for "Any" container returns the container entity definition itself plus the path that is to - * be searched in the given "Any" container. However, there's no point in repeating the search there, - * as it would yield the same result. - */ - public abstract DefinitionSearchResult nextDefinition(ItemPath path) throws QueryException; - - /** - * Resolves the whole ItemPath. - * - * If successful, returns either: - * - correct definition + empty path, or - * - Any definition + path remainder - * - * If unsuccessful, return null. - * - * @return - */ - public DefinitionSearchResult findDefinition(ItemPath path, Class type) throws QueryException { - JpaDefinition currentDefinition = this; - for (;;) { - if (ItemPath.isNullOrEmpty(path)) { // we are at the end of search - hoping we found the correct class - if (type.isAssignableFrom(currentDefinition.getClass())) { - return new DefinitionSearchResult<>((D) currentDefinition, null); - } else { - return null; - } - } - if (currentDefinition instanceof JpaAnyDefinition) { - if (type.isAssignableFrom(JpaAnyDefinition.class)) { - return new DefinitionSearchResult<>((D) currentDefinition, path); - } else { - return null; - } - } - DefinitionSearchResult result = currentDefinition.nextDefinition(path); - if (result == null) { // oops - return null; - } - currentDefinition = result.getItemDefinition(); - path = result.getRemainder(); - } - } - - /** - * Translates ItemPath to a sequence of definitions. - * - * @param itemPath - * @return The translation (if successful) or null (if not successful). - * For "Any" elements, the last element in the path is Any. - * - * Note: structurally similar to findDefinition above - */ - -// public DefinitionPath translatePath(ItemPath itemPath) throws QueryException { -// ItemPath originalPath = itemPath; // we remember original path just for logging -// DefinitionPath definitionPath = new DefinitionPath(); -// -// JpaDefinition currentDefinition = this; -// for (;;) { -// if (currentDefinition instanceof JpaAnyDefinition || ItemPath.isNullOrEmpty(itemPath)) { -// LOGGER.trace("ItemPath {} translated to DefinitionPath {} (started in {})", originalPath, definitionPath, this); -// return definitionPath; -// } -// DefinitionSearchResult result = currentDefinition.nextDefinition(itemPath); -// LOGGER.trace("nextDefinition on {} returned {}", itemPath, result != null ? result.getItemDefinition() : "(null)"); -// if (result == null) { -// return null; // sorry we failed -// } -// JpaItemDefinition nextDefinition = result.getItemDefinition(); -// definitionPath.add(nextDefinition); -// -// itemPath = result.getRemainder(); -// currentDefinition = nextDefinition; -// } -// } - - public String toString() { - return getDebugDumpClassName() + ":" + jpaClass.getSimpleName(); - } - - protected abstract String getDebugDumpClassName(); - - @Override - public String debugDump() { - return debugDump(0); - } - - protected String dumpQName(QName qname) { - if (qname == null) { - return null; - } - - String namespace = qname.getNamespaceURI(); - namespace = namespace.replaceFirst("http://midpoint\\.evolveum\\.com/xml/ns/public", ".."); - - StringBuilder builder = new StringBuilder(); - builder.append('{'); - builder.append(namespace); - builder.append('}'); - builder.append(qname.getLocalPart()); - return builder.toString(); - } - -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java deleted file mode 100644 index 61c64e371c1..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityContentDefinition.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.Visitable; -import com.evolveum.midpoint.prism.Visitor; -import com.evolveum.midpoint.prism.path.IdItemPathSegment; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.ItemPathSegment; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; -import com.evolveum.midpoint.prism.path.ParentPathSegment; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import org.apache.commons.lang.Validate; - -import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author mederly - */ -public class JpaEntityContentDefinition implements DebugDumpable, Visitable { - - /** - * child definitions of this entity - */ - private List definitions; - private JpaRootEntityDefinition superclassDefinition; - - public void addDefinition(JpaItemDefinition definition) { - if (definitions == null) { - definitions = new ArrayList<>(); - } - JpaItemDefinition oldDef = findDefinition(definition.getJaxbName(), JpaItemDefinition.class); - if (oldDef != null) { - definitions.remove(oldDef); - } - definitions.add(definition); - } - - public D findDefinition(QName jaxbName, Class type) { - Validate.notNull(jaxbName, "Jaxb name must not be null."); - Validate.notNull(type, "Definition type must not be null."); - - for (JpaItemDefinition definition : definitions) { - if (!QNameUtil.match(jaxbName, definition.getJaxbName())){ - continue; - } - if (type.isAssignableFrom(definition.getClass())) { - return (D) definition; - } - } - return null; - } - - public void setSuperclassDefinition(JpaRootEntityDefinition superclassDefinition) { - this.superclassDefinition = superclassDefinition; - } - - public JpaRootEntityDefinition getSuperclassDefinition() { - return superclassDefinition; - } - - public DefinitionSearchResult nextDefinition(JpaEntityDefinition owningDefinition, ItemPath path) throws QueryException { - - // first treat known discrepancies between prism structure and repo representation: - // metadata -> none, - // construction/resourceRef -> resourceRef - while (skipFirstItem(path, owningDefinition)) { - path = path.tail(); - } - - // now find the definition - if (ItemPath.isNullOrEmpty(path)) { - // note that for wrong input (e.g. path=metadata) this answer might be wrong, but we don't care - // return new DefinitionSearchResult(owningDefinition, null); - return null; - } - - QName firstName = ((NameItemPathSegment) path.first()).getName(); - JpaItemDefinition def = findDefinition(firstName, JpaItemDefinition.class); - if (def == null) { - return null; - } else { - return new DefinitionSearchResult(def, path.tail()); - } - } - - - private boolean skipFirstItem(ItemPath path, JpaEntityDefinition owningDefinition) throws QueryException { - if (ItemPath.isNullOrEmpty(path)) { - return false; - } - ItemPathSegment first = path.first(); - if (first instanceof IdItemPathSegment) { - throw new QueryException("ID path segments are not allowed in query: " + path); - } else if (first instanceof ObjectReferencePathSegment) { - throw new QueryException("'@' path segment cannot be used in the context of an entity " + owningDefinition); - } else if (first instanceof ParentPathSegment) { - throw new UnsupportedOperationException("TODO"); - } - - QName firstName = ((NameItemPathSegment) first).getName(); - - // metadata -> null - if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { - return true; - } - - // construction/resourceRef -> construction - ItemPath remainder = path.tail(); - if (remainder.isEmpty() || !(remainder.first() instanceof NameItemPathSegment)) { - return false; - } - NameItemPathSegment second = ((NameItemPathSegment) (remainder.first())); - QName secondName = second.getName(); - if (QNameUtil.match(firstName, AssignmentType.F_CONSTRUCTION) && - QNameUtil.match(secondName, ConstructionType.F_RESOURCE_REF)) { - return true; - } - return false; - } - - - @Override - public void accept(Visitor visitor) { - visitor.visit(this); - for (JpaItemDefinition definition : definitions) { - definition.accept(visitor); - } - } - - public String debugDump(int indent) { - StringBuilder sb = new StringBuilder(); - DebugUtil.indentDebugDump(sb, indent); - sb.append("Superclass: ").append(superclassDefinition).append(", definitions (").append(definitions.size()).append("):\n"); - for (JpaItemDefinition definition : definitions) { - sb.append(definition.debugDump(indent+1)).append("\n"); - } - return sb.toString(); - } - - @Override - public String debugDump() { - return debugDump(0); - } -} - diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java index 18d871e3086..7c16bc5750e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java @@ -16,22 +16,253 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathSegment; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; +import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** + * @author lazyman * @author mederly */ -public interface JpaEntityDefinition { +public class JpaEntityDefinition extends JpaDataNodeDefinition implements DebugDumpable, Visitable { + + private static final Trace LOGGER = TraceManager.getTrace(JpaEntityDefinition.class); + + /** + * child definitions of this entity + */ + private List definitions = new ArrayList<>(); + private JpaEntityDefinition superclassDefinition; + + public JpaEntityDefinition(Class jpaClass, Class jaxbClass) { + super(jpaClass, jaxbClass); + } + + public void addDefinition(JpaLinkDefinition definition) { + JpaLinkDefinition oldDef = findLinkDefinition(definition.getItemPathSegment(), JpaDataNodeDefinition.class); + if (oldDef != null) { + definitions.remove(oldDef); + } + definitions.add(definition); + } + + public void sortDefinitions() { + Collections.sort(definitions, new LinkDefinitionComparator()); + } + + private JpaLinkDefinition findLinkDefinition(ItemPathSegment itemPathSegment, Class type) { + Validate.notNull(itemPathSegment, "ItemPathSegment must not be null."); + Validate.notNull(type, "Definition type must not be null."); + + for (JpaLinkDefinition definition : definitions) { + if (!definition.matches(itemPathSegment)) { + continue; + } + if (type.isAssignableFrom(definition.getTargetClass())) { + return definition; + } + } + return null; + } + + public interface LinkDefinitionHandler { + void handle(JpaLinkDefinition linkDefinition); + } + + /** + * Resolves the whole ItemPath (non-empty!) + * + * If successful, returns either: + * - correct definition + empty path, or + * - Any definition + path remainder + * + * If unsuccessful, return null. + * + * @return + */ + public DataSearchResult findDataNodeDefinition(ItemPath path, Class type) throws QueryException { + return findDataNodeDefinition(path, type, null); + } + + public DataSearchResult findDataNodeDefinition(ItemPath path, Class type, LinkDefinitionHandler handler) throws QueryException { + JpaDataNodeDefinition currentDefinition = this; + for (;;) { + DataSearchResult result = currentDefinition.nextLinkDefinition(path); + if (result == null) { // oops + return null; + } + if (handler != null) { + handler.handle(result.getLinkDefinition()); + } + JpaLinkDefinition linkDefinition = result.getLinkDefinition(); + JpaDataNodeDefinition targetDefinition = linkDefinition.getTargetDefinition(); + + if (result.isComplete() || targetDefinition instanceof JpaAnyDefinition) { + if (type.isAssignableFrom(targetDefinition.getClass())) { + return (DataSearchResult) result; + } else { + return null; + } + } + + path = result.getRemainder(); + currentDefinition = targetDefinition; + } + } + + /** + * Translates ItemPath to a sequence of definitions. + * + * @param itemPath + * @return The translation (if successful) or null (if not successful). + * For "Any" elements, the last element in the path is Any. + */ + + public DefinitionPath translatePath(ItemPath itemPath) throws QueryException { + final DefinitionPath definitionPath = new DefinitionPath(); + DataSearchResult result = findDataNodeDefinition(itemPath, JpaDataNodeDefinition.class, new LinkDefinitionHandler() { + @Override + public void handle(JpaLinkDefinition linkDefinition) { + definitionPath.add(linkDefinition); + } + }); + if (result != null) { + LOGGER.trace("ItemPath {} successfully translated to DefinitionPath {} (started in {})", itemPath, definitionPath, this); + return definitionPath; + } else { + LOGGER.trace("ItemPath {} PARTIALLY translated to DefinitionPath {} (started in {})", itemPath, definitionPath, this); + return null; + } + } - Class getJpaClass(); + public void setSuperclassDefinition(JpaEntityDefinition superclassDefinition) { + this.superclassDefinition = superclassDefinition; + } - String getJpaClassName(); + public JpaEntityDefinition getSuperclassDefinition() { + return superclassDefinition; + } - boolean isAbstract(); + @Override + public DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException { - boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition); + // first treat known discrepancies between prism structure and repo representation: + // metadata -> none, + // construction/resourceRef -> resourceRef + // + // TODO replace with the use of VirtualEntity with null jpaName + while (skipFirstItem(path)) { + path = path.tail(); + } - DefinitionSearchResult findDefinition(ItemPath path, Class clazz) throws QueryException; + if (ItemPath.isNullOrEmpty(path)) { // doesn't fulfill precondition + return null; + } + + JpaLinkDefinition link = findLinkDefinition(path.first(), JpaDataNodeDefinition.class); + if (link == null) { + return null; + } else { + link.resolveEntityPointer(); + return new DataSearchResult(link, path.tail()); + } + } + + + private boolean skipFirstItem(ItemPath path) throws QueryException { + if (ItemPath.isNullOrEmpty(path)) { + return false; + } + ItemPathSegment first = path.first(); + if (first instanceof IdItemPathSegment) { + throw new QueryException("ID path segments are not allowed in query: " + path); + } else if (first instanceof ObjectReferencePathSegment) { + throw new QueryException("'@' path segment cannot be used in the context of an entity " + this); + } else if (first instanceof ParentPathSegment) { + return false; + } + + QName firstName = ((NameItemPathSegment) first).getName(); + + // metadata -> null + if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { + return true; + } + + // construction/resourceRef -> construction + ItemPath remainder = path.tail(); + if (remainder.isEmpty() || !(remainder.first() instanceof NameItemPathSegment)) { + return false; + } + NameItemPathSegment second = ((NameItemPathSegment) (remainder.first())); + QName secondName = second.getName(); + if (QNameUtil.match(firstName, AssignmentType.F_CONSTRUCTION) && + QNameUtil.match(secondName, ConstructionType.F_RESOURCE_REF)) { + return true; + } + return false; + } + + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + for (JpaLinkDefinition definition : definitions) { + definition.accept(visitor); + } + } + + @Override + protected String getDebugDumpClassName() { + return "Ent"; + } + + @Override + public String debugDump() { + return debugDump(0); + } + + public boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition) { + return getJpaClass().isAssignableFrom(specificEntityDefinition.getJpaClass()); + } + + public boolean isAbstract() { + return Modifier.isAbstract(getJpaClass().getModifiers()); + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + sb.append(super.getShortInfo()); + if (superclassDefinition != null) { + sb.append(" extends ").append(superclassDefinition); + } + for (JpaLinkDefinition definition : definitions) { + sb.append("\n"); + sb.append(definition.debugDump(indent + 1)); + } + return sb.toString(); + } } + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java deleted file mode 100644 index d6fef024cfd..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityItemDefinition.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.Visitor; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import org.apache.commons.lang.Validate; - -import javax.xml.namespace.QName; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author lazyman - */ -public class JpaEntityItemDefinition extends JpaItemDefinition implements JpaEntityDefinition { - - private boolean embedded; - private JpaEntityContentDefinition content; - - public JpaEntityItemDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, Class jpaClass, JpaEntityContentDefinition content, boolean embedded) { - super(jaxbName, jpaName, collectionSpecification, jpaClass); - Validate.notNull(content, "content"); - this.content = content; - this.embedded = embedded; - } - - public boolean isEmbedded() { - return embedded; - } - - public JpaEntityContentDefinition getContent() { - return content; - } - - @Override - protected void debugDumpExtended(StringBuilder sb, int indent) { - sb.append(", embedded=").append(embedded).append("\n"); - sb.append(content.debugDump(indent + 1)); - } - - @Override - public DefinitionSearchResult nextDefinition(ItemPath path) throws QueryException { - return content.nextDefinition(this, path); - } - - @Override - protected String getDebugDumpClassName() { - return "Ent"; - } - - @Override - public void accept(Visitor visitor) { - visitor.visit(this); - content.accept(visitor); - } - - // the following methods are duplicate with JpaRootEntityDefinition - @Override - public boolean isAbstract() { - return Modifier.isAbstract(getJpaClass().getModifiers()); - } - - @Override - public boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition) { - return getJpaClass().isAssignableFrom(specificEntityDefinition.getJpaClass()); - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java new file mode 100644 index 00000000000..8aab6ffbce8 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; + +/** + * Special placeholder to allow for cross-references: entity definition that points to another entity. + * (TODO) + * + * @author mederly + */ +public class JpaEntityPointerDefinition extends JpaDataNodeDefinition { + + private JpaEntityDefinition resolvedEntityDefinition; // lazily evaluated + + public JpaEntityPointerDefinition(Class jpaClass) { + super(jpaClass, null); + } + + public JpaEntityDefinition getResolvedEntityDefinition() { + return resolvedEntityDefinition; + } + + public void setResolvedEntityDefinition(JpaEntityDefinition resolvedEntityDefinition) { + this.resolvedEntityDefinition = resolvedEntityDefinition; + } + + @Override + public DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException { + return resolvedEntityDefinition.nextLinkDefinition(path); + } + + @Override + protected String getDebugDumpClassName() { + return "EntPtr"; + } + + @Override + public String debugDump(int indent) { + if (resolvedEntityDefinition == null) { + return getShortInfo(); + } else { + return getDebugDumpClassName() + ":" + resolvedEntityDefinition.getShortInfo(); + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java deleted file mode 100644 index 469a5734b90..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaItemDefinition.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.util.DebugUtil; -import org.apache.commons.lang.Validate; - -import javax.xml.namespace.QName; - -/** - * Specifies an item - something that is included in an entity. - * - * @author mederly - */ -public abstract class JpaItemDefinition extends JpaDefinition { - - /** - * Name in ItemPath by which is this item to be retrieved. - */ - private QName jaxbName; - - /** - * Name that is used when constructing HQL queries. Must correspond to the name of Rxxx class property. - * Some virtual items (namely, object extension and shadow attributes; in future maybe metadata and construction) - * have no JPA name. They are accessed directly from their base entity. - */ - private String jpaName; - - /** - * Multiplicity and (optionally) parameters used to construct a join to retrieve the values. - */ - private CollectionSpecification collectionSpecification; - - public JpaItemDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, Class jpaClass) { - super(jpaClass); - Validate.notNull(jaxbName, "jaxbName"); - this.jaxbName = jaxbName; - this.jpaName = jpaName; - this.collectionSpecification = collectionSpecification; - } - - public QName getJaxbName() { - return jaxbName; - } - - public String getJpaName() { - return jpaName; - } - - public CollectionSpecification getCollectionSpecification() { - return collectionSpecification; - } - - public boolean isMultivalued() { - return collectionSpecification != null; - } - - @Override - public String debugDump(int indent) { - StringBuilder sb = new StringBuilder(); - DebugUtil.indentDebugDump(sb, indent); - sb.append(getDebugDumpClassName()).append(": ").append(getJaxbName()); - if (collectionSpecification != null) { - sb.append(collectionSpecification.getShortInfo()); - } - sb.append(" => ").append(jpaName).append(" (").append(getJpaClass().getSimpleName()).append(")"); - debugDumpExtended(sb, indent); - return sb.toString(); - } - - protected abstract void debugDumpExtended(StringBuilder sb, int indent); -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java new file mode 100644 index 00000000000..69cb54dad2c --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.Visitable; +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPathSegment; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; + +/** + * @author mederly + */ +public class JpaLinkDefinition implements Visitable, DebugDumpable { + + private ItemPathSegment itemPathSegment; + private String jpaName; // beware - null for "same entity" transitions (metadata, construction, ...) + private CollectionSpecification collectionSpecification; // null if single valued + private boolean embedded; + private D targetDefinition; + + public JpaLinkDefinition(ItemPathSegment itemPathSegment, String jpaName, CollectionSpecification collectionSpecification, D targetDefinition) { + this(itemPathSegment, jpaName, collectionSpecification, false, targetDefinition); + } + + public JpaLinkDefinition(ItemPathSegment itemPathSegment, String jpaName, CollectionSpecification collectionSpecification, boolean embedded, D targetDefinition) { + Validate.notNull(itemPathSegment, "itemPathSegment"); + Validate.notNull(targetDefinition, "targetDefinition"); + this.itemPathSegment = itemPathSegment; + this.jpaName = jpaName; + this.collectionSpecification = collectionSpecification; + this.embedded = embedded; + this.targetDefinition = targetDefinition; + } + + public JpaLinkDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, D targetDefinition) { + this(jaxbName, jpaName, collectionSpecification, false, targetDefinition); + } + + public JpaLinkDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, boolean embedded, D targetDefinition) { + this(new NameItemPathSegment(jaxbName), jpaName, collectionSpecification, embedded, targetDefinition); + Validate.notNull(jaxbName, "jaxbName"); // "this" must be the first - validation is better late than never ;) + + } + + public ItemPathSegment getItemPathSegment() { + return itemPathSegment; + } + + public String getJpaName() { + return jpaName; + } + + public CollectionSpecification getCollectionSpecification() { + return collectionSpecification; + } + + public boolean isEmbedded() { + return embedded; + } + + public D getTargetDefinition() { + return targetDefinition; + } + + public boolean matches(ItemPathSegment itemPathSegment) { + return this.itemPathSegment.equivalent(itemPathSegment); + } + + public Class getTargetClass() { + return (Class) targetDefinition.getClass(); + } + + public boolean isMultivalued() { + return collectionSpecification != null; + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + targetDefinition.accept(visitor); + } + + @Override + public String debugDump() { + return debugDump(0); + } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + dumpLink(sb); + sb.append(targetDefinition.debugDump(indent + 1)); + return sb.toString(); + } + + private void dumpLink(StringBuilder sb) { + sb.append(itemPathSegment.toString()).append(" => ").append(jpaName); + if (collectionSpecification != null) { + sb.append(collectionSpecification.getShortInfo()); + } + if (embedded) { + sb.append(" (embedded)"); + } + sb.append(" -> "); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + dumpLink(sb); + sb.append(targetDefinition.getShortInfo()); + return sb.toString(); + } + + public void resolveEntityPointer() { + if (targetDefinition instanceof JpaEntityPointerDefinition) { + // typing hack but we don't mind + targetDefinition = (D) ((JpaEntityPointerDefinition) targetDefinition).getResolvedEntityDefinition(); + } + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java index 170a9ba1e55..17383f86f5f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java @@ -19,14 +19,12 @@ import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; - -import javax.xml.namespace.QName; +import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; /** * @author lazyman */ -public class JpaPropertyDefinition extends JpaItemDefinition { +public class JpaPropertyDefinition extends JpaDataNodeDefinition { //jpa special types private boolean lob; @@ -34,9 +32,8 @@ public class JpaPropertyDefinition extends JpaItemDefinition { //jpa special things private boolean indexed; - public JpaPropertyDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, - Class jpaClass, boolean lob, boolean enumerated, boolean indexed) { - super(jaxbName, jpaName, collectionSpecification, jpaClass); + public JpaPropertyDefinition(Class jpaClass, Class jaxbClass, boolean lob, boolean enumerated, boolean indexed) { + super(jpaClass, jaxbClass); this.lob = lob; this.enumerated = enumerated; this.indexed = indexed; @@ -70,20 +67,13 @@ void setIndexed(boolean indexed) { this.indexed = indexed; } - @Override - protected void debugDumpExtended(StringBuilder builder, int indent) { - builder.append(", lob=").append(isLob()); - builder.append(", enumerated=").append(isEnumerated()); - builder.append(", indexed=").append(isIndexed()); - } - @Override protected String getDebugDumpClassName() { return "Prop"; } @Override - public DefinitionSearchResult nextDefinition(ItemPath path) { + public DataSearchResult nextLinkDefinition(ItemPath path) { // nowhere to come from here return null; } @@ -92,4 +82,20 @@ public DefinitionSearchResult nextDefinition(ItemPath path) { public void accept(Visitor visitor) { visitor.visit(this); } + + @Override + public String debugDump(int indent) { + StringBuilder sb = new StringBuilder(); + sb.append(super.getShortInfo()); + if (isLob()) { + sb.append(", lob"); + } + if (isEnumerated()) { + sb.append(", enumerated"); + } + if (isIndexed()) { + sb.append(", indexed"); + } + return sb.toString(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java index 735fa6299e3..4eade85e4c2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java @@ -16,43 +16,23 @@ package com.evolveum.midpoint.repo.sql.query2.definition; -import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; +import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; import org.apache.commons.lang.Validate; -import javax.xml.namespace.QName; - /** * @author lazyman */ -public class JpaReferenceDefinition extends JpaItemDefinition { +public class JpaReferenceDefinition extends JpaDataNodeDefinition { - private JpaRootEntityDefinition referencedEntityDefinition; // lazily evaluated - private Class referencedEntityJpaClass; - private boolean embedded; + private JpaEntityPointerDefinition referencedEntityDefinition; // lazily evaluated - public JpaReferenceDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, - Class jpaClass, Class referencedEntityJpaClass, boolean embedded) { - super(jaxbName, jpaName, collectionSpecification, jpaClass); - this.embedded = embedded; + public JpaReferenceDefinition(Class jpaClass, Class referencedEntityJpaClass) { + super(jpaClass, null); // JAXB class not important here Validate.notNull(referencedEntityJpaClass, "referencedEntityJpaClass"); - this.referencedEntityJpaClass = referencedEntityJpaClass; - } - - public boolean isEmbedded() { - return embedded; - } - - void setEmbedded(boolean embedded) { - this.embedded = embedded; - } - - @Override - protected void debugDumpExtended(StringBuilder builder, int indent) { - builder.append(", embedded=").append(isEmbedded()).append(", referencedEntity: ").append(referencedEntityDefinition); + this.referencedEntityDefinition = new JpaEntityPointerDefinition(referencedEntityJpaClass); } @Override @@ -61,32 +41,34 @@ protected String getDebugDumpClassName() { } @Override - public DefinitionSearchResult nextDefinition(ItemPath path) { + public DataSearchResult nextLinkDefinition(ItemPath path) { if (path.first() instanceof ObjectReferencePathSegment) { - // returning artificially created item definition, used to allow dereferencing target object in a generic way - return new DefinitionSearchResult( - new JpaEntityItemDefinition(PrismConstants.T_OBJECT_REFERENCE, "target", null, - referencedEntityDefinition.getJpaClass(), referencedEntityDefinition.getContent(), false), + // returning artificially created transition definition, used to allow dereferencing target object in a generic way + return new DataSearchResult( + new JpaLinkDefinition(new ObjectReferencePathSegment(), "target", null, referencedEntityDefinition.getResolvedEntityDefinition()), path.tail()); } else { return null; } } + public JpaEntityPointerDefinition getReferencedEntityDefinition() { + return referencedEntityDefinition; + } + @Override public void accept(Visitor visitor) { visitor.visit(this); + referencedEntityDefinition.accept(visitor); } - public void setReferencedEntityDefinition(JpaRootEntityDefinition realEntDef) { - this.referencedEntityDefinition = realEntDef; - } - - public JpaRootEntityDefinition getReferencedEntityDefinition() { - return referencedEntityDefinition; + @Override + public String debugDump(int indent) { + return super.getShortInfo() + ", target=" + getReferencedEntityDefinition(); } - public Class getReferencedEntityJpaClass() { - return referencedEntityJpaClass; + @Override + public String getShortInfo() { + return super.getShortInfo() + "<" + referencedEntityDefinition.getJpaClassName() + ">"; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java deleted file mode 100644 index 3dc2085c071..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaRootEntityDefinition.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import com.evolveum.midpoint.prism.Visitor; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DefinitionSearchResult; -import com.evolveum.midpoint.util.DebugUtil; -import org.apache.commons.lang.Validate; - -import java.lang.reflect.Modifier; - -/** - * @author mederly - */ -public class JpaRootEntityDefinition extends JpaDefinition implements JpaEntityDefinition { - - private JpaEntityContentDefinition content; - - public JpaRootEntityDefinition(Class jpaClass, JpaEntityContentDefinition content) { - super(jpaClass); - Validate.notNull(content, "content"); - this.content = content; - } - - public JpaEntityContentDefinition getContent() { - return content; - } - - public boolean isAssignableFrom(JpaEntityDefinition specificEntityDefinition) { - return getJpaClass().isAssignableFrom(specificEntityDefinition.getJpaClass()); - } - - public boolean isAbstract() { - return Modifier.isAbstract(getJpaClass().getModifiers()); - } - - @Override - public void accept(Visitor visitor) { - visitor.visit(this); - content.accept(visitor); - } - - @Override - protected String getDebugDumpClassName() { - return "RootEnt"; - } - - @Override - public String debugDump(int indent) { - StringBuilder sb = new StringBuilder(); - DebugUtil.indentDebugDump(sb, indent); - sb.append(getDebugDumpClassName()).append(":").append(getJpaClass().getSimpleName()).append(":\n"); - sb.append(content.debugDump(indent + 1)); - return sb.toString(); - } - - @Override - public DefinitionSearchResult nextDefinition(ItemPath path) throws QueryException { - return content.nextDefinition(this, path); - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java similarity index 63% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java index b061fa8fdd3..7eb3a1be358 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionComparator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java @@ -21,19 +21,22 @@ /** * @author lazyman */ -public class DefinitionComparator implements Comparator { +public class LinkDefinitionComparator implements Comparator { @Override - public int compare(JpaItemDefinition o1, JpaItemDefinition o2) { - if (o1.getClass().equals(o2.getClass())) { - return String.CASE_INSENSITIVE_ORDER.compare(o1.getJaxbName().getLocalPart(), - o2.getJaxbName().getLocalPart()); + public int compare(JpaLinkDefinition o1, JpaLinkDefinition o2) { + JpaDataNodeDefinition target1 = o1.getTargetDefinition(); + JpaDataNodeDefinition target2 = o2.getTargetDefinition(); + + if (target1.equals(target2)) { + return String.CASE_INSENSITIVE_ORDER.compare(o1.getItemPathSegment().toString(), + o2.getItemPathSegment().toString()); } - return getType(o1) - getType(o2); + return getType(target1) - getType(target2); } - private int getType(JpaItemDefinition def) { + private int getType(JpaDataNodeDefinition def) { if (def == null) { return 0; } @@ -43,7 +46,7 @@ private int getType(JpaItemDefinition def) { return 2; } else if (def instanceof JpaAnyDefinition) { return 4; - } else if (def instanceof JpaEntityItemDefinition) { + } else if (def instanceof JpaEntityDefinition) { return 5; } return 0; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java index ff2b155ba0f..9388e22591b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java @@ -20,8 +20,6 @@ import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import org.apache.commons.lang.Validate; -import javax.xml.namespace.QName; - /** * @author mederly */ @@ -29,8 +27,8 @@ public class VirtualAnyDefinition extends JpaAnyDefinition { private RObjectExtensionType ownerType; // ObjectType (for extension) or ShadowType (for attributes) - public VirtualAnyDefinition(QName jaxbName, RObjectExtensionType ownerType) { - super(jaxbName, null, RObject.class); // RObject is artificial - don't want to make jpaClass nullable just for this single situation + public VirtualAnyDefinition(RObjectExtensionType ownerType) { + super(RObject.class); // RObject is artificial - don't want to make jpaClass nullable just for this single situation Validate.notNull(ownerType, "ownerType"); this.ownerType = ownerType; } @@ -45,7 +43,7 @@ protected String getDebugDumpClassName() { } @Override - protected void debugDumpExtended(StringBuilder sb, int indent) { - sb.append(", ownerType=").append(ownerType); + public String debugDump(int indent) { + return super.debugDump(indent) + ", ownerType=" + ownerType; } -} +} \ No newline at end of file diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index cb6c51ceccb..db71e82058e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -20,8 +20,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import org.apache.commons.lang.Validate; @@ -61,7 +60,7 @@ public abstract class HibernateQuery { private String orderByProperty; private OrderDirection orderDirection; - public HibernateQuery(JpaRootEntityDefinition primaryEntityDef) { + public HibernateQuery(JpaEntityDefinition primaryEntityDef) { Validate.notNull(primaryEntityDef, "primaryEntityDef"); primaryEntity = createItemSpecification(primaryEntityDef); } @@ -138,8 +137,9 @@ public String createAlias(JpaEntityDefinition def) { return createAlias(def.getJpaClassName(), true); } - public String createAlias(JpaItemDefinition joinedItemDef) { - return createAlias(joinedItemDef.getJpaName(), false); + public String createAlias(JpaLinkDefinition linkDefinition) { + Validate.notNull(linkDefinition.getJpaName(), "Got unnamed transition"); + return createAlias(linkDefinition.getJpaName(), false); } private static final int LIMIT = 100; @@ -185,7 +185,7 @@ public void setOrder(String propertyPath, OrderDirection direction) { public abstract RootHibernateQuery getRootQuery(); // used to narrow the primary entity e.g. from RObject to RUser (e.g. during ItemValueRestriction processing) - public void narrowPrimaryEntity(JpaRootEntityDefinition newDefinition) throws QueryException { + public void narrowPrimaryEntity(JpaEntityDefinition newDefinition) throws QueryException { String oldEntityName = getPrimaryEntity().getName(); Class oldEntityClass = ClassMapper.getHqlClassForHqlName(oldEntityName); Class newEntityClass = newDefinition.getJpaClass(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java index b656297cf02..961a20c5677 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java @@ -16,8 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2.hqm; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.InCondition; @@ -51,7 +50,7 @@ public class RootHibernateQuery extends HibernateQuery { private Integer firstResult; private ResultTransformer resultTransformer; - public RootHibernateQuery(JpaRootEntityDefinition primaryEntityDef) { + public RootHibernateQuery(JpaEntityDefinition primaryEntityDef) { super(primaryEntityDef); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java index abc0aefa53a..1d32fb916b1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/HibernateSubquery.java @@ -16,7 +16,7 @@ package com.evolveum.midpoint.repo.sql.query2.hqm.condition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaRootEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import org.apache.commons.lang.Validate; @@ -28,7 +28,7 @@ public class HibernateSubquery extends HibernateQuery { private HibernateQuery parentQuery; - public HibernateSubquery(JpaRootEntityDefinition primaryEntityDef, HibernateQuery parentQuery) { + public HibernateSubquery(JpaEntityDefinition primaryEntityDef, HibernateQuery parentQuery) { super(primaryEntityDef); Validate.notNull(parentQuery); this.parentQuery = parentQuery; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index 92a6fc38483..7b3b5c9ec22 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -26,7 +26,6 @@ import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.exception.SchemaException; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java index e2933049c4c..2e9c5cc3d56 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -131,74 +131,6 @@ protected Object getValue(List values) { return null; } - protected Object getValueFromFilter(ValueFilter filter, JpaPropertyDefinition def) throws QueryException { - Object value; - if (filter instanceof PropertyValueFilter) { - value = getValue(((PropertyValueFilter) filter).getValues()); - } else { - throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); - } - - Class expectedType = def.getJpaClass(); - if (expectedType.isPrimitive()) { - expectedType = ClassUtils.primitiveToWrapper(expectedType); - } else if (expectedType.equals(RPolyString.class)) { - expectedType = PolyString.class; - } - - //todo remove after some time [lazyman] - //attempt to fix value type for polystring (if it was string in filter we create polystring from it) - if (PolyString.class.equals(expectedType) && (value instanceof String)) { - LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", filter); - value = new PolyString((String) value, (String) value); - } - //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) - if (PolyString.class.equals(expectedType) && (value instanceof PolyStringType)) { - LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", filter); - PolyStringType type = (PolyStringType) value; - value = new PolyString(type.getOrig(), type.getNorm()); - } - - if (String.class.equals(expectedType) && (value instanceof QName)) { - //eg. shadow/objectClass - value = RUtil.qnameToString((QName) value); - } - - if (value != null && !expectedType.isAssignableFrom(value.getClass())) { - throw new QueryException("Value should be type of '" + expectedType + "' but it's '" - + value.getClass() + "', filter '" + filter + "'."); - } - - if (def.isEnumerated()) { - value = getRepoEnumValue((Enum) value, def.getJpaClass()); - } - - return value; - } - - private Enum getRepoEnumValue(Enum schemaValue, Class repoType) throws QueryException { - if (schemaValue == null) { - return null; - } - - if (SchemaEnum.class.isAssignableFrom(repoType)) { - return (Enum) RUtil.getRepoEnumValue(schemaValue, repoType); - } - - Object[] constants = repoType.getEnumConstants(); - for (Object constant : constants) { - Enum e = (Enum) constant; - if (e.name().equals(schemaValue.name())) { - return e; - } - } - - throw new QueryException("Unknown enum value '" + schemaValue + "', which is type of '" - + schemaValue.getClass() + "'."); - } - - - /** * Filter of type NOT(PROPERTY=VALUE) causes problems when there are entities with PROPERTY set to NULL. * diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java index aa3e8c29b20..790636e3595 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/NaryLogicalRestriction.java @@ -18,11 +18,10 @@ import com.evolveum.midpoint.prism.query.NaryLogicalFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.JunctionCondition; import com.evolveum.midpoint.util.logging.Trace; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index 262187df513..73d50376048 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -16,16 +16,25 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.Validate; +import javax.xml.namespace.QName; + /** * @author lazyman */ @@ -33,31 +42,103 @@ public class PropertyRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(PropertyRestriction.class); - JpaPropertyDefinition jpaPropertyDefinition; + private JpaLinkDefinition linkDefinition; public PropertyRestriction(InterpretationContext context, ValueFilter filter, JpaEntityDefinition baseEntityDefinition, - Restriction parent, JpaPropertyDefinition jpaPropertyDefinition) { + Restriction parent, JpaLinkDefinition linkDefinition) { super(context, filter, baseEntityDefinition, parent); - Validate.notNull(jpaPropertyDefinition, "propertyDefinition"); - this.jpaPropertyDefinition = jpaPropertyDefinition; + Validate.notNull(linkDefinition, "linkDefinition"); + this.linkDefinition = linkDefinition; } @Override public Condition interpretInternal(String hqlPath) throws QueryException { - if (jpaPropertyDefinition.isLob()) { - throw new QueryException("Can't query based on clob property value '" + jpaPropertyDefinition + "'."); + if (linkDefinition.getTargetDefinition().isLob()) { + throw new QueryException("Can't query based on clob property value '" + linkDefinition + "'."); } - String propertyFullName; - if (jpaPropertyDefinition.isMultivalued()) { - propertyFullName = hqlPath; + Object value = getValueFromFilter(filter); + Condition condition = createCondition(hqlPath, value, filter); + + return addIsNotNullIfNecessary(condition, hqlPath); + } + + protected Object getValueFromFilter(ValueFilter filter) throws QueryException { + + JpaPropertyDefinition def = linkDefinition.getTargetDefinition(); + + Object value; + if (filter instanceof PropertyValueFilter) { + value = getValue(((PropertyValueFilter) filter).getValues()); } else { - propertyFullName = hqlPath + "." + jpaPropertyDefinition.getJpaName(); + throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); + } + + value = checkValueType(value, filter); + + if (def.isEnumerated()) { + value = getRepoEnumValue((Enum) value, def.getJpaClass()); } - Object value = getValueFromFilter(filter, jpaPropertyDefinition); - Condition condition = createCondition(propertyFullName, value, filter); - return addIsNotNullIfNecessary(condition, propertyFullName); + return value; } + + private Object checkValueType(Object value, ValueFilter filter) throws QueryException { + + Class expectedType = linkDefinition.getTargetDefinition().getJaxbClass(); + if (expectedType == null || value == null) { + return value; // nothing to check here + } + + if (expectedType.isPrimitive()) { + expectedType = ClassUtils.primitiveToWrapper(expectedType); + } + + //todo remove after some time [lazyman] + //attempt to fix value type for polystring (if it was string in filter we create polystring from it) + if (PolyString.class.equals(expectedType) && (value instanceof String)) { + LOGGER.debug("Trying to query PolyString value but filter contains String '{}'.", filter); + value = new PolyString((String) value, (String) value); + } + //attempt to fix value type for polystring (if it was polystringtype in filter we create polystring from it) + if (PolyString.class.equals(expectedType) && (value instanceof PolyStringType)) { + LOGGER.debug("Trying to query PolyString value but filter contains PolyStringType '{}'.", filter); + PolyStringType type = (PolyStringType) value; + value = new PolyString(type.getOrig(), type.getNorm()); + } + + if (String.class.equals(expectedType) && (value instanceof QName)) { + //eg. shadow/objectClass + value = RUtil.qnameToString((QName) value); + } + + if (!expectedType.isAssignableFrom(value.getClass())) { + throw new QueryException("Value should be type of '" + expectedType + "' but it's '" + + value.getClass() + "', filter '" + filter + "'."); + } + return value; + } + + private Enum getRepoEnumValue(Enum schemaValue, Class repoType) throws QueryException { + if (schemaValue == null) { + return null; + } + + if (SchemaEnum.class.isAssignableFrom(repoType)) { + return (Enum) RUtil.getRepoEnumValue(schemaValue, repoType); + } + + Object[] constants = repoType.getEnumConstants(); + for (Object constant : constants) { + Enum e = (Enum) constant; + if (e.name().equals(schemaValue.name())) { + return e; + } + } + + throw new QueryException("Unknown enum value '" + schemaValue + "', which is type of '" + + schemaValue.getClass() + "'."); + } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index 99121a808c9..ea1c67e1e7d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -24,8 +24,8 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -46,13 +46,13 @@ public class ReferenceRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(ReferenceRestriction.class); // Definition of the item being queried. - private final JpaReferenceDefinition itemDefinition; + private final JpaLinkDefinition linkDefinition; public ReferenceRestriction(InterpretationContext context, RefFilter filter, JpaEntityDefinition baseEntityDefinition, - Restriction parent, JpaReferenceDefinition itemDefinition) { + Restriction parent, JpaLinkDefinition linkDefinition) { super(context, filter, baseEntityDefinition, parent); - Validate.notNull(itemDefinition, "itemDefinition"); - this.itemDefinition = itemDefinition; + Validate.notNull(linkDefinition, "linkDefinition"); + this.linkDefinition = linkDefinition; } @Override @@ -72,13 +72,6 @@ public Condition interpretInternal(String hqlPath) throws QueryException { InterpretationContext context = getContext(); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - String propertyFullNamePrefix; - if (itemDefinition.isMultivalued()) { - propertyFullNamePrefix = hqlPath + "."; - } else { - propertyFullNamePrefix = hqlPath + "." + itemDefinition.getJpaName() + "."; - } - String refValueOid = null; QName refValueRelation = null; QName refValueTargetType = null; @@ -88,21 +81,21 @@ public Condition interpretInternal(String hqlPath) throws QueryException { refValueTargetType = refValue.getTargetType(); } AndCondition conjunction = hibernateQuery.createAnd(); - conjunction.add(handleEqOrNull(hibernateQuery, propertyFullNamePrefix + ObjectReference.F_TARGET_OID, refValueOid)); + conjunction.add(handleEqOrNull(hibernateQuery, hqlPath + "." + ObjectReference.F_TARGET_OID, refValueOid)); if (refValueOid != null) { if (refValueRelation == null) { // Return only references without relation - conjunction.add(hibernateQuery.createEq(propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); + conjunction.add(hibernateQuery.createEq(hqlPath + "." + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER)); } else if (refValueRelation.equals(PrismConstants.Q_ANY)) { // Return all relations => no restriction } else { // return references with specific relation - conjunction.add(handleEqOrNull(hibernateQuery, propertyFullNamePrefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); + conjunction.add(handleEqOrNull(hibernateQuery, hqlPath + "." + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation))); } if (refValueTargetType != null) { - conjunction.add(handleEqOrNull(hibernateQuery, propertyFullNamePrefix + ObjectReference.F_TYPE, + conjunction.add(handleEqOrNull(hibernateQuery, hqlPath + "." + ObjectReference.F_TYPE, ClassMapper.getHQLTypeForQName(refValueTargetType))); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index f3948e01073..7746a8f07db 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -19,11 +19,10 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.InterpreterHelper; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import org.apache.commons.lang.Validate; import org.hibernate.Session; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java index e33ff366236..7345fbe2318 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -23,7 +23,6 @@ import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.util.ClassMapper; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java index 7041cd24c1b..6e0d010344a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/UnaryLogicalRestriction.java @@ -21,7 +21,6 @@ import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityItemDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; From 131d44cd1e1c4ef48bc23a90fef1bc96934c2cbf Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 28 Nov 2015 23:07:17 +0100 Subject: [PATCH 024/116] Fixing behavior for malformed ItemPaths. --- .../main/java/com/evolveum/midpoint/prism/path/ItemPath.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index 9eccef24eab..b2d3f8f6c46 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -147,9 +147,9 @@ public static ItemPath subPath(ItemPath prefix, ItemPathSegment subSegment) { } private void add(QName qname) { - if (qname.equals(PrismConstants.T_PARENT)) { + if (PrismConstants.T_PARENT.equals(qname)) { this.segments.add(new ParentPathSegment()); - } else if (qname.equals(PrismConstants.T_OBJECT_REFERENCE)) { + } else if (PrismConstants.T_OBJECT_REFERENCE.equals(qname)) { this.segments.add(new ObjectReferencePathSegment()); } else { this.segments.add(new NameItemPathSegment(qname)); From b5133050f05c827872f7dd7e523199cff9cc29fa Mon Sep 17 00:00:00 2001 From: gpalos Date: Sun, 29 Nov 2015 00:04:21 +0100 Subject: [PATCH 025/116] - workaround for MID-2723 to examples - upgrade demo to MP 3.3. and new LDAPConn --- samples/demo/PageLogin.html | 12 + samples/demo/PageTemplate.html | 228 ++-- samples/demo/opendj.xml | 1120 +++++------------ samples/demo/org.xml | 2 +- samples/demo/orgs-metaRole.xml | 2 +- samples/demo/projects-metaRole.xml | 4 +- samples/demo/role-fte.xml | 2 +- .../389ds/389ds-localhost-medium.xml | 11 +- .../opendj/opendj-localhost-basic.xml | 10 + .../opendj/opendj-localhost-medium.xml | 13 +- ...pendj-localhost-resource-sync-advanced.xml | 20 +- ...-resource-sync-no-extension-advanced-2.xml | 19 +- ...source-sync-no-extension-advanced-test.xml | 32 +- ...st-resource-sync-no-extension-advanced.xml | 9 + .../opendj/opendj-resource-genericsync.xml | 10 + ...ocalhost-advanced-sync-modifytimestamp.xml | 11 +- .../openldap/openldap-localhost-medium.xml | 14 +- samples/tasks/recon-task-opendj-test.xml | 6 +- .../account/ResourceUserAccountTests.java | 18 +- .../tests/basictests/CsvAccountTests.java | 2 +- 20 files changed, 591 insertions(+), 954 deletions(-) diff --git a/samples/demo/PageLogin.html b/samples/demo/PageLogin.html index adbe4e4b7e0..bf10b218aa8 100644 --- a/samples/demo/PageLogin.html +++ b/samples/demo/PageLogin.html @@ -75,6 +75,18 @@ + + This css is used to hide sidebar menu + diff --git a/samples/demo/PageTemplate.html b/samples/demo/PageTemplate.html index 3ee06369e70..477244c2a13 100644 --- a/samples/demo/PageTemplate.html +++ b/samples/demo/PageTemplate.html @@ -23,105 +23,189 @@ - - - - - + + + + + + - - + + - + - - + + - - + + - + - + - - - + + + - + - - - - + + + + - - + + - - - + + + - + - + - - - - -

-
- -
+ + + -
+ -
- -
- + + + + + + -
-
- + - - + + -
-
-
-
- + + + + -
+ + + -
- Clear css cache + + + + + + + + +
+
+ + + + +
+ + + +
+ +
+

+ + + +

+ +
+ + +
+
+
+
+
+ + + +
+
-
+
+ + +
- - -
+
From d8bb6f806204c04e043eaa8ea90e3089508b4cb4 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 12:18:13 +0100 Subject: [PATCH 032/116] Full and upgrade DB scripts for PostgreSQL. --- ...sql-3.2-all.sql => postgresql-3.3-all.sql} | 74 +++++++++++---- .../sql/_all/postgresql-upgrade-3.1.1-3.2.sql | 32 ------- .../sql/_all/postgresql-upgrade-3.2-3.3.sql | 95 ++++++++++--------- ...{postgresql-3.2.sql => postgresql-3.3.sql} | 74 +++++++++++---- .../postgresql-upgrade-3.1.1-3.2.sql | 32 ------- .../postgresql/postgresql-upgrade-3.2-3.3.sql | 65 +++++++++++++ 6 files changed, 225 insertions(+), 147 deletions(-) rename config/sql/_all/{postgresql-3.2-all.sql => postgresql-3.3-all.sql} (97%) delete mode 100644 config/sql/_all/postgresql-upgrade-3.1.1-3.2.sql rename config/sql/midpoint/3.3/postgresql/{postgresql-3.2.sql => postgresql-3.3.sql} (95%) delete mode 100644 config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.1.1-3.2.sql create mode 100644 config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.2-3.3.sql diff --git a/config/sql/_all/postgresql-3.2-all.sql b/config/sql/_all/postgresql-3.3-all.sql similarity index 97% rename from config/sql/_all/postgresql-3.2-all.sql rename to config/sql/_all/postgresql-3.3-all.sql index cf0db1290cd..b1e9d0df435 100644 --- a/config/sql/_all/postgresql-3.2-all.sql +++ b/config/sql/_all/postgresql-3.3-all.sql @@ -47,6 +47,12 @@ CREATE TABLE m_assignment ( modifyChannel VARCHAR(255), modifyTimestamp TIMESTAMP, orderValue INT4, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INT4, + resourceRef_relation VARCHAR(157), + resourceRef_targetOid VARCHAR(36), + resourceRef_type INT4, targetRef_relation VARCHAR(157), targetRef_targetOid VARCHAR(36), targetRef_type INT4, @@ -156,13 +162,18 @@ CREATE TABLE m_assignment_reference ( ); CREATE TABLE m_audit_delta ( - checksum VARCHAR(32) NOT NULL, - record_id INT8 NOT NULL, - delta TEXT, - deltaOid VARCHAR(36), - deltaType INT4, - fullResult TEXT, - status INT4, + checksum VARCHAR(32) NOT NULL, + record_id INT8 NOT NULL, + delta TEXT, + deltaOid VARCHAR(36), + deltaType INT4, + fullResult TEXT, + objectName_norm VARCHAR(255), + objectName_orig VARCHAR(255), + resourceName_norm VARCHAR(255), + resourceName_orig VARCHAR(255), + resourceOid VARCHAR(36), + status INT4, PRIMARY KEY (checksum, record_id) ); @@ -240,10 +251,17 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus INT4, + hasPhoto BOOLEAN DEFAULT FALSE NOT NULL, oid VARCHAR(36) NOT NULL, PRIMARY KEY (oid) ); +CREATE TABLE m_focus_photo ( + owner_oid VARCHAR(36) NOT NULL, + photo BYTEA, + PRIMARY KEY (owner_oid) +); + CREATE TABLE m_generic_object ( name_norm VARCHAR(255), name_orig VARCHAR(255), @@ -468,6 +486,13 @@ CREATE TABLE m_security_policy ( PRIMARY KEY (oid) ); +CREATE TABLE m_sequence ( + name_norm VARCHAR(255), + name_orig VARCHAR(255), + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) +); + CREATE TABLE m_shadow ( attemptNumber INT4, dead BOOLEAN, @@ -549,7 +574,6 @@ CREATE TABLE m_user ( fullName_orig VARCHAR(255), givenName_norm VARCHAR(255), givenName_orig VARCHAR(255), - hasPhoto BOOLEAN NOT NULL, honorificPrefix_norm VARCHAR(255), honorificPrefix_orig VARCHAR(255), honorificSuffix_norm VARCHAR(255), @@ -588,12 +612,6 @@ CREATE TABLE m_user_organizational_unit ( orig VARCHAR(255) ); -CREATE TABLE m_user_photo ( - owner_oid VARCHAR(36) NOT NULL, - photo BYTEA, - PRIMARY KEY (owner_oid) -); - CREATE TABLE m_value_policy ( name_norm VARCHAR(255), name_orig VARCHAR(255), @@ -613,6 +631,14 @@ CREATE INDEX iAssignmentAdministrative ON m_assignment (administrativeStatus); CREATE INDEX iAssignmentEffective ON m_assignment (effectiveStatus); +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); + +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); + +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); + +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + CREATE INDEX iAExtensionBoolean ON m_assignment_ext_boolean (extensionType, eName, booleanValue); CREATE INDEX iAExtensionDate ON m_assignment_ext_date (extensionType, eName, dateValue); @@ -627,6 +653,8 @@ CREATE INDEX iAExtensionString ON m_assignment_ext_string (extensionType, eName, CREATE INDEX iAssignmentReferenceTargetOid ON m_assignment_reference (targetOid); +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + ALTER TABLE m_connector_host ADD CONSTRAINT uc_connector_host_name UNIQUE (name_norm); @@ -708,6 +736,9 @@ ADD CONSTRAINT uc_role_name UNIQUE (name_norm); ALTER TABLE m_security_policy ADD CONSTRAINT uc_security_policy_name UNIQUE (name_norm); +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + CREATE INDEX iShadowResourceRef ON m_shadow (resourceRef_targetOid); CREATE INDEX iShadowDead ON m_shadow (dead); @@ -820,6 +851,11 @@ ADD CONSTRAINT fk_focus FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + ALTER TABLE m_generic_object ADD CONSTRAINT fk_generic_object FOREIGN KEY (oid) @@ -925,6 +961,11 @@ ADD CONSTRAINT fk_security_policy FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + ALTER TABLE m_shadow ADD CONSTRAINT fk_shadow FOREIGN KEY (oid) @@ -970,11 +1011,6 @@ ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user; -ALTER TABLE m_user_photo -ADD CONSTRAINT fk_user_photo -FOREIGN KEY (owner_oid) -REFERENCES m_user; - ALTER TABLE m_value_policy ADD CONSTRAINT fk_value_policy FOREIGN KEY (oid) diff --git a/config/sql/_all/postgresql-upgrade-3.1.1-3.2.sql b/config/sql/_all/postgresql-upgrade-3.1.1-3.2.sql deleted file mode 100644 index a64d8d28199..00000000000 --- a/config/sql/_all/postgresql-upgrade-3.1.1-3.2.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) -); - -CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR(157), - definitionRef_targetOid VARCHAR(36), - definitionRef_type int4, - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) -); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT fk_acc_cert_definition - FOREIGN KEY (oid) - REFERENCES m_object; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT fk_acc_cert_campaign - FOREIGN KEY (oid) - REFERENCES m_object; diff --git a/config/sql/_all/postgresql-upgrade-3.2-3.3.sql b/config/sql/_all/postgresql-upgrade-3.2-3.3.sql index 93b4d88ca1a..e851871e3e8 100644 --- a/config/sql/_all/postgresql-upgrade-3.2-3.3.sql +++ b/config/sql/_all/postgresql-upgrade-3.2-3.3.sql @@ -1,60 +1,65 @@ -create table m_sequence ( - name_norm varchar(255), - name_orig varchar(255), - oid varchar(36) not null, - primary key (oid) +CREATE TABLE m_sequence ( + name_norm VARCHAR(255), + name_orig VARCHAR(255), + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) ); -alter table m_sequence - add constraint uc_sequence_name unique (name_norm); +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); -alter table m_sequence - add constraint fk_sequence - foreign key (oid) - references m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; -alter table m_user_photo rename to m_focus_photo; +ALTER TABLE m_user_photo RENAME TO m_focus_photo; -alter table m_focus add hasPhoto boolean not null default FALSE; -update m_focus set hasPhoto = false; -update m_focus set hasPhoto = (select hasPhoto from m_user where m_user.oid = m_focus.oid) - where m_focus.oid in (select oid from m_user); +ALTER TABLE m_focus ADD hasPhoto BOOLEAN NOT NULL DEFAULT FALSE; +UPDATE m_focus +SET hasPhoto = FALSE; +UPDATE m_focus +SET hasPhoto = (SELECT hasPhoto + FROM m_user + WHERE m_user.oid = m_focus.oid) +WHERE m_focus.oid IN (SELECT oid + FROM m_user); -alter table m_focus_photo - drop constraint m_user_photo_pkey; +ALTER TABLE m_focus_photo +DROP CONSTRAINT m_user_photo_pkey; -alter table m_focus_photo - add constraint m_focus_photo_pkey primary key(owner_oid); +ALTER TABLE m_focus_photo +ADD CONSTRAINT m_focus_photo_pkey PRIMARY KEY (owner_oid); -alter table m_focus_photo - drop constraint fk_user_photo; +ALTER TABLE m_focus_photo +DROP CONSTRAINT fk_user_photo; -alter table m_focus_photo - add constraint fk_focus_photo - foreign key (owner_oid) - references m_focus; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; -alter table m_user drop column hasPhoto; +ALTER TABLE m_user DROP COLUMN hasPhoto; -alter table m_assignment - add orgRef_relation varchar(157), - add orgRef_targetOid varchar(36), - add orgRef_type int4, - add resourceRef_relation varchar(157), - add resourceRef_targetOid varchar(36), - add resourceRef_type int4; +ALTER TABLE m_assignment +ADD orgRef_relation VARCHAR(157), +ADD orgRef_targetOid VARCHAR(36), +ADD orgRef_type INT4, +ADD resourceRef_relation VARCHAR(157), +ADD resourceRef_targetOid VARCHAR(36), +ADD resourceRef_type INT4; -create index iTargetRefTargetOid on m_assignment (targetRef_targetOid); -create index iTenantRefTargetOid on m_assignment (tenantRef_targetOid); -create index iOrgRefTargetOid on m_assignment (orgRef_targetOid); -create index iResourceRefTargetOid on m_assignment (resourceRef_targetOid); +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); -create index iTimestampValue on m_audit_event (timestampValue); +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); -alter table m_audit_delta - add objectName_norm varchar(255), - add objectName_orig varchar(255), - add resourceName_norm varchar(255), - add resourceName_orig varchar(255), - add resourceOid varchar(36); +ALTER TABLE m_audit_delta +ADD objectName_norm VARCHAR(255), +ADD objectName_orig VARCHAR(255), +ADD resourceName_norm VARCHAR(255), +ADD resourceName_orig VARCHAR(255), +ADD resourceOid VARCHAR(36); diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-3.2.sql b/config/sql/midpoint/3.3/postgresql/postgresql-3.3.sql similarity index 95% rename from config/sql/midpoint/3.3/postgresql/postgresql-3.2.sql rename to config/sql/midpoint/3.3/postgresql/postgresql-3.3.sql index 7c61625f18d..3a18ff1c6c0 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-3.2.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-3.3.sql @@ -47,6 +47,12 @@ CREATE TABLE m_assignment ( modifyChannel VARCHAR(255), modifyTimestamp TIMESTAMP, orderValue INT4, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INT4, + resourceRef_relation VARCHAR(157), + resourceRef_targetOid VARCHAR(36), + resourceRef_type INT4, targetRef_relation VARCHAR(157), targetRef_targetOid VARCHAR(36), targetRef_type INT4, @@ -156,13 +162,18 @@ CREATE TABLE m_assignment_reference ( ); CREATE TABLE m_audit_delta ( - checksum VARCHAR(32) NOT NULL, - record_id INT8 NOT NULL, - delta TEXT, - deltaOid VARCHAR(36), - deltaType INT4, - fullResult TEXT, - status INT4, + checksum VARCHAR(32) NOT NULL, + record_id INT8 NOT NULL, + delta TEXT, + deltaOid VARCHAR(36), + deltaType INT4, + fullResult TEXT, + objectName_norm VARCHAR(255), + objectName_orig VARCHAR(255), + resourceName_norm VARCHAR(255), + resourceName_orig VARCHAR(255), + resourceOid VARCHAR(36), + status INT4, PRIMARY KEY (checksum, record_id) ); @@ -240,10 +251,17 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus INT4, + hasPhoto BOOLEAN DEFAULT FALSE NOT NULL, oid VARCHAR(36) NOT NULL, PRIMARY KEY (oid) ); +CREATE TABLE m_focus_photo ( + owner_oid VARCHAR(36) NOT NULL, + photo BYTEA, + PRIMARY KEY (owner_oid) +); + CREATE TABLE m_generic_object ( name_norm VARCHAR(255), name_orig VARCHAR(255), @@ -468,6 +486,13 @@ CREATE TABLE m_security_policy ( PRIMARY KEY (oid) ); +CREATE TABLE m_sequence ( + name_norm VARCHAR(255), + name_orig VARCHAR(255), + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) +); + CREATE TABLE m_shadow ( attemptNumber INT4, dead BOOLEAN, @@ -549,7 +574,6 @@ CREATE TABLE m_user ( fullName_orig VARCHAR(255), givenName_norm VARCHAR(255), givenName_orig VARCHAR(255), - hasPhoto BOOLEAN NOT NULL, honorificPrefix_norm VARCHAR(255), honorificPrefix_orig VARCHAR(255), honorificSuffix_norm VARCHAR(255), @@ -588,12 +612,6 @@ CREATE TABLE m_user_organizational_unit ( orig VARCHAR(255) ); -CREATE TABLE m_user_photo ( - owner_oid VARCHAR(36) NOT NULL, - photo BYTEA, - PRIMARY KEY (owner_oid) -); - CREATE TABLE m_value_policy ( name_norm VARCHAR(255), name_orig VARCHAR(255), @@ -613,6 +631,14 @@ CREATE INDEX iAssignmentAdministrative ON m_assignment (administrativeStatus); CREATE INDEX iAssignmentEffective ON m_assignment (effectiveStatus); +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); + +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); + +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); + +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + CREATE INDEX iAExtensionBoolean ON m_assignment_ext_boolean (extensionType, eName, booleanValue); CREATE INDEX iAExtensionDate ON m_assignment_ext_date (extensionType, eName, dateValue); @@ -627,6 +653,8 @@ CREATE INDEX iAExtensionString ON m_assignment_ext_string (extensionType, eName, CREATE INDEX iAssignmentReferenceTargetOid ON m_assignment_reference (targetOid); +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + ALTER TABLE m_connector_host ADD CONSTRAINT uc_connector_host_name UNIQUE (name_norm); @@ -708,6 +736,9 @@ ADD CONSTRAINT uc_role_name UNIQUE (name_norm); ALTER TABLE m_security_policy ADD CONSTRAINT uc_security_policy_name UNIQUE (name_norm); +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + CREATE INDEX iShadowResourceRef ON m_shadow (resourceRef_targetOid); CREATE INDEX iShadowDead ON m_shadow (dead); @@ -820,6 +851,11 @@ ADD CONSTRAINT fk_focus FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + ALTER TABLE m_generic_object ADD CONSTRAINT fk_generic_object FOREIGN KEY (oid) @@ -925,6 +961,11 @@ ADD CONSTRAINT fk_security_policy FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + ALTER TABLE m_shadow ADD CONSTRAINT fk_shadow FOREIGN KEY (oid) @@ -970,11 +1011,6 @@ ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user; -ALTER TABLE m_user_photo -ADD CONSTRAINT fk_user_photo -FOREIGN KEY (owner_oid) -REFERENCES m_user; - ALTER TABLE m_value_policy ADD CONSTRAINT fk_value_policy FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.1.1-3.2.sql b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.1.1-3.2.sql deleted file mode 100644 index a64d8d28199..00000000000 --- a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.1.1-3.2.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) -); - -CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR(157), - definitionRef_targetOid VARCHAR(36), - definitionRef_type int4, - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) -); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT fk_acc_cert_definition - FOREIGN KEY (oid) - REFERENCES m_object; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT fk_acc_cert_campaign - FOREIGN KEY (oid) - REFERENCES m_object; diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.2-3.3.sql b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.2-3.3.sql new file mode 100644 index 00000000000..e851871e3e8 --- /dev/null +++ b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.2-3.3.sql @@ -0,0 +1,65 @@ +CREATE TABLE m_sequence ( + name_norm VARCHAR(255), + name_orig VARCHAR(255), + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) +); + +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + +ALTER TABLE m_user_photo RENAME TO m_focus_photo; + +ALTER TABLE m_focus ADD hasPhoto BOOLEAN NOT NULL DEFAULT FALSE; +UPDATE m_focus +SET hasPhoto = FALSE; +UPDATE m_focus +SET hasPhoto = (SELECT hasPhoto + FROM m_user + WHERE m_user.oid = m_focus.oid) +WHERE m_focus.oid IN (SELECT oid + FROM m_user); + +ALTER TABLE m_focus_photo +DROP CONSTRAINT m_user_photo_pkey; + +ALTER TABLE m_focus_photo +ADD CONSTRAINT m_focus_photo_pkey PRIMARY KEY (owner_oid); + +ALTER TABLE m_focus_photo +DROP CONSTRAINT fk_user_photo; + +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + +ALTER TABLE m_user DROP COLUMN hasPhoto; + +ALTER TABLE m_assignment +ADD orgRef_relation VARCHAR(157), +ADD orgRef_targetOid VARCHAR(36), +ADD orgRef_type INT4, +ADD resourceRef_relation VARCHAR(157), +ADD resourceRef_targetOid VARCHAR(36), +ADD resourceRef_type INT4; + +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + +ALTER TABLE m_audit_delta +ADD objectName_norm VARCHAR(255), +ADD objectName_orig VARCHAR(255), +ADD resourceName_norm VARCHAR(255), +ADD resourceName_orig VARCHAR(255), +ADD resourceOid VARCHAR(36); + From b3addd44195a1e6b88241de78c0c8113ed5e9584 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 12:34:42 +0100 Subject: [PATCH 033/116] Full and upgrade DB scripts for SQL Server. --- ...rver-3.2-all.sql => sqlserver-3.3-all.sql} | 74 +++++++++--- .../sql/_all/sqlserver-upgrade-3.1.1-3.2.sql | 32 ----- config/sql/_all/sqlserver-upgrade-3.2-3.3.sql | 109 +++++++++--------- .../{sqlserver-3.2.sql => sqlserver-3.3.sql} | 74 +++++++++--- .../sqlserver/sqlserver-upgrade-3.1.1-3.2.sql | 32 ----- .../sqlserver/sqlserver-upgrade-3.2-3.3.sql | 60 ++++++++++ 6 files changed, 227 insertions(+), 154 deletions(-) rename config/sql/_all/{sqlserver-3.2-all.sql => sqlserver-3.3-all.sql} (97%) delete mode 100644 config/sql/_all/sqlserver-upgrade-3.1.1-3.2.sql rename config/sql/midpoint/3.3/sqlserver/{sqlserver-3.2.sql => sqlserver-3.3.sql} (94%) delete mode 100644 config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.1.1-3.2.sql create mode 100644 config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.2-3.3.sql diff --git a/config/sql/_all/sqlserver-3.2-all.sql b/config/sql/_all/sqlserver-3.3-all.sql similarity index 97% rename from config/sql/_all/sqlserver-3.2-all.sql rename to config/sql/_all/sqlserver-3.3-all.sql index b4d52dbe9ca..31fb052f1cf 100644 --- a/config/sql/_all/sqlserver-3.2-all.sql +++ b/config/sql/_all/sqlserver-3.3-all.sql @@ -47,6 +47,12 @@ CREATE TABLE m_assignment ( modifyChannel NVARCHAR(255) COLLATE database_default, modifyTimestamp DATETIME2, orderValue INT, + orgRef_relation NVARCHAR(157) COLLATE database_default, + orgRef_targetOid NVARCHAR(36) COLLATE database_default, + orgRef_type INT, + resourceRef_relation NVARCHAR(157) COLLATE database_default, + resourceRef_targetOid NVARCHAR(36) COLLATE database_default, + resourceRef_type INT, targetRef_relation NVARCHAR(157) COLLATE database_default, targetRef_targetOid NVARCHAR(36) COLLATE database_default, targetRef_type INT, @@ -156,13 +162,18 @@ CREATE TABLE m_assignment_reference ( ); CREATE TABLE m_audit_delta ( - checksum NVARCHAR(32) COLLATE database_default NOT NULL, - record_id BIGINT NOT NULL, - delta NVARCHAR(MAX), - deltaOid NVARCHAR(36) COLLATE database_default, - deltaType INT, - fullResult NVARCHAR(MAX), - status INT, + checksum NVARCHAR(32) COLLATE database_default NOT NULL, + record_id BIGINT NOT NULL, + delta NVARCHAR(MAX), + deltaOid NVARCHAR(36) COLLATE database_default, + deltaType INT, + fullResult NVARCHAR(MAX), + objectName_norm NVARCHAR(255) COLLATE database_default, + objectName_orig NVARCHAR(255) COLLATE database_default, + resourceName_norm NVARCHAR(255) COLLATE database_default, + resourceName_orig NVARCHAR(255) COLLATE database_default, + resourceOid NVARCHAR(36) COLLATE database_default, + status INT, PRIMARY KEY (checksum, record_id) ); @@ -240,10 +251,17 @@ CREATE TABLE m_focus ( validTo DATETIME2, validityChangeTimestamp DATETIME2, validityStatus INT, + hasPhoto BIT DEFAULT FALSE NOT NULL, oid NVARCHAR(36) COLLATE database_default NOT NULL, PRIMARY KEY (oid) ); +CREATE TABLE m_focus_photo ( + owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + photo VARBINARY(MAX), + PRIMARY KEY (owner_oid) +); + CREATE TABLE m_generic_object ( name_norm NVARCHAR(255) COLLATE database_default, name_orig NVARCHAR(255) COLLATE database_default, @@ -468,6 +486,13 @@ CREATE TABLE m_security_policy ( PRIMARY KEY (oid) ); +CREATE TABLE m_sequence ( + name_norm NVARCHAR(255) COLLATE database_default, + name_orig NVARCHAR(255) COLLATE database_default, + oid NVARCHAR(36) COLLATE database_default NOT NULL, + PRIMARY KEY (oid) +); + CREATE TABLE m_shadow ( attemptNumber INT, dead BIT, @@ -549,7 +574,6 @@ CREATE TABLE m_user ( fullName_orig NVARCHAR(255) COLLATE database_default, givenName_norm NVARCHAR(255) COLLATE database_default, givenName_orig NVARCHAR(255) COLLATE database_default, - hasPhoto BIT NOT NULL, honorificPrefix_norm NVARCHAR(255) COLLATE database_default, honorificPrefix_orig NVARCHAR(255) COLLATE database_default, honorificSuffix_norm NVARCHAR(255) COLLATE database_default, @@ -588,12 +612,6 @@ CREATE TABLE m_user_organizational_unit ( orig NVARCHAR(255) COLLATE database_default ); -CREATE TABLE m_user_photo ( - owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, - photo VARBINARY(MAX), - PRIMARY KEY (owner_oid) -); - CREATE TABLE m_value_policy ( name_norm NVARCHAR(255) COLLATE database_default, name_orig NVARCHAR(255) COLLATE database_default, @@ -613,6 +631,14 @@ CREATE INDEX iAssignmentAdministrative ON m_assignment (administrativeStatus); CREATE INDEX iAssignmentEffective ON m_assignment (effectiveStatus); +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); + +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); + +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); + +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + CREATE INDEX iAExtensionBoolean ON m_assignment_ext_boolean (extensionType, eName, booleanValue); CREATE INDEX iAExtensionDate ON m_assignment_ext_date (extensionType, eName, dateValue); @@ -627,6 +653,8 @@ CREATE INDEX iAExtensionString ON m_assignment_ext_string (extensionType, eName, CREATE INDEX iAssignmentReferenceTargetOid ON m_assignment_reference (targetOid); +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + ALTER TABLE m_connector_host ADD CONSTRAINT uc_connector_host_name UNIQUE (name_norm); @@ -708,6 +736,9 @@ ADD CONSTRAINT uc_role_name UNIQUE (name_norm); ALTER TABLE m_security_policy ADD CONSTRAINT uc_security_policy_name UNIQUE (name_norm); +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + CREATE INDEX iShadowResourceRef ON m_shadow (resourceRef_targetOid); CREATE INDEX iShadowDead ON m_shadow (dead); @@ -820,6 +851,11 @@ ADD CONSTRAINT fk_focus FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + ALTER TABLE m_generic_object ADD CONSTRAINT fk_generic_object FOREIGN KEY (oid) @@ -925,6 +961,11 @@ ADD CONSTRAINT fk_security_policy FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + ALTER TABLE m_shadow ADD CONSTRAINT fk_shadow FOREIGN KEY (oid) @@ -970,11 +1011,6 @@ ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user; -ALTER TABLE m_user_photo -ADD CONSTRAINT fk_user_photo -FOREIGN KEY (owner_oid) -REFERENCES m_user; - ALTER TABLE m_value_policy ADD CONSTRAINT fk_value_policy FOREIGN KEY (oid) diff --git a/config/sql/_all/sqlserver-upgrade-3.1.1-3.2.sql b/config/sql/_all/sqlserver-upgrade-3.1.1-3.2.sql deleted file mode 100644 index fc73f83fb67..00000000000 --- a/config/sql/_all/sqlserver-upgrade-3.1.1-3.2.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE m_acc_cert_definition ( - name_norm NVARCHAR(255) COLLATE database_default, - name_orig NVARCHAR(255) COLLATE database_default, - oid NVARCHAR(36) COLLATE database_default NOT NULL, - PRIMARY KEY (oid) -); - -CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation NVARCHAR(157) COLLATE database_default, - definitionRef_targetOid NVARCHAR(36) COLLATE database_default, - definitionRef_type INT, - name_norm NVARCHAR(255) COLLATE database_default, - name_orig NVARCHAR(255) COLLATE database_default, - oid NVARCHAR(36) COLLATE database_default NOT NULL, - PRIMARY KEY (oid) -); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT fk_acc_cert_definition - FOREIGN KEY (oid) - REFERENCES m_object; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT fk_acc_cert_campaign - FOREIGN KEY (oid) - REFERENCES m_object; diff --git a/config/sql/_all/sqlserver-upgrade-3.2-3.3.sql b/config/sql/_all/sqlserver-upgrade-3.2-3.3.sql index 3ba48fd908e..d5f0ea148ae 100644 --- a/config/sql/_all/sqlserver-upgrade-3.2-3.3.sql +++ b/config/sql/_all/sqlserver-upgrade-3.2-3.3.sql @@ -1,55 +1,60 @@ -create table m_sequence ( - name_norm nvarchar(255) collate database_default, - name_orig nvarchar(255) collate database_default, - oid nvarchar(36) collate database_default not null, - primary key (oid) +CREATE TABLE m_sequence ( + name_norm NVARCHAR(255) COLLATE database_default, + name_orig NVARCHAR(255) COLLATE database_default, + oid NVARCHAR(36) COLLATE database_default NOT NULL, + PRIMARY KEY (oid) ); -alter table m_sequence - add constraint uc_sequence_name unique (name_norm); - -alter table m_sequence - add constraint fk_sequence - foreign key (oid) - references m_object; - -exec sp_rename m_user_photo, m_focus_photo; - -alter table m_focus add hasPhoto bit not null constraint default_constraint default 0; - -update m_focus set hasPhoto = 0; - update m_focus set hasPhoto = (select hasPhoto from m_user where m_user.oid = m_focus.oid) - where m_focus.oid in (select oid from m_user); - -alter table m_user drop column hasPhoto; - -alter table m_focus_photo - drop constraint fk_user_photo; - -alter table m_focus_photo - add constraint fk_focus_photo - foreign key (owner_oid) - references m_focus; - -alter table m_assignment add - orgRef_relation nvarchar(157) collate database_default, - orgRef_targetOid nvarchar(36) collate database_default, - orgRef_type int, - resourceRef_relation nvarchar(157) collate database_default, - resourceRef_targetOid nvarchar(36) collate database_default, - resourceRef_type int; - -create index iTargetRefTargetOid on m_assignment (targetRef_targetOid); -create index iTenantRefTargetOid on m_assignment (tenantRef_targetOid); -create index iOrgRefTargetOid on m_assignment (orgRef_targetOid); -create index iResourceRefTargetOid on m_assignment (resourceRef_targetOid); - -create index iTimestampValue on m_audit_event (timestampValue); - -alter table m_audit_delta add - objectName_norm nvarchar(255) collate database_default, - objectName_orig nvarchar(255) collate database_default, - resourceName_norm nvarchar(255) collate database_default, - resourceName_orig nvarchar(255) collate database_default, - resourceOid nvarchar(36) collate database_default; +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + +EXEC sp_rename m_user_photo, m_focus_photo; + +ALTER TABLE m_focus ADD hasPhoto BIT NOT NULL CONSTRAINT default_constraint DEFAULT 0; + +UPDATE m_focus +SET hasPhoto = 0; +UPDATE m_focus +SET hasPhoto = (SELECT hasPhoto + FROM m_user + WHERE m_user.oid = m_focus.oid) +WHERE m_focus.oid IN (SELECT oid + FROM m_user); + +ALTER TABLE m_user DROP COLUMN hasPhoto; + +ALTER TABLE m_focus_photo +DROP CONSTRAINT fk_user_photo; + +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + +ALTER TABLE m_assignment ADD +orgRef_relation NVARCHAR(157) COLLATE database_default, +orgRef_targetOid NVARCHAR(36) COLLATE database_default, +orgRef_type INT, +resourceRef_relation NVARCHAR(157) COLLATE database_default, +resourceRef_targetOid NVARCHAR(36) COLLATE database_default, +resourceRef_type INT; + +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + +ALTER TABLE m_audit_delta ADD +objectName_norm NVARCHAR(255) COLLATE database_default, +objectName_orig NVARCHAR(255) COLLATE database_default, +resourceName_norm NVARCHAR(255) COLLATE database_default, +resourceName_orig NVARCHAR(255) COLLATE database_default, +resourceOid NVARCHAR(36) COLLATE database_default; diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.2.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql similarity index 94% rename from config/sql/midpoint/3.3/sqlserver/sqlserver-3.2.sql rename to config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql index 9edd975af1b..c05f068cb0e 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.2.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql @@ -47,6 +47,12 @@ CREATE TABLE m_assignment ( modifyChannel NVARCHAR(255) COLLATE database_default, modifyTimestamp DATETIME2, orderValue INT, + orgRef_relation NVARCHAR(157) COLLATE database_default, + orgRef_targetOid NVARCHAR(36) COLLATE database_default, + orgRef_type INT, + resourceRef_relation NVARCHAR(157) COLLATE database_default, + resourceRef_targetOid NVARCHAR(36) COLLATE database_default, + resourceRef_type INT, targetRef_relation NVARCHAR(157) COLLATE database_default, targetRef_targetOid NVARCHAR(36) COLLATE database_default, targetRef_type INT, @@ -156,13 +162,18 @@ CREATE TABLE m_assignment_reference ( ); CREATE TABLE m_audit_delta ( - checksum NVARCHAR(32) COLLATE database_default NOT NULL, - record_id BIGINT NOT NULL, - delta NVARCHAR(MAX), - deltaOid NVARCHAR(36) COLLATE database_default, - deltaType INT, - fullResult NVARCHAR(MAX), - status INT, + checksum NVARCHAR(32) COLLATE database_default NOT NULL, + record_id BIGINT NOT NULL, + delta NVARCHAR(MAX), + deltaOid NVARCHAR(36) COLLATE database_default, + deltaType INT, + fullResult NVARCHAR(MAX), + objectName_norm NVARCHAR(255) COLLATE database_default, + objectName_orig NVARCHAR(255) COLLATE database_default, + resourceName_norm NVARCHAR(255) COLLATE database_default, + resourceName_orig NVARCHAR(255) COLLATE database_default, + resourceOid NVARCHAR(36) COLLATE database_default, + status INT, PRIMARY KEY (checksum, record_id) ); @@ -240,10 +251,17 @@ CREATE TABLE m_focus ( validTo DATETIME2, validityChangeTimestamp DATETIME2, validityStatus INT, + hasPhoto BIT DEFAULT FALSE NOT NULL, oid NVARCHAR(36) COLLATE database_default NOT NULL, PRIMARY KEY (oid) ); +CREATE TABLE m_focus_photo ( + owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + photo VARBINARY(MAX), + PRIMARY KEY (owner_oid) +); + CREATE TABLE m_generic_object ( name_norm NVARCHAR(255) COLLATE database_default, name_orig NVARCHAR(255) COLLATE database_default, @@ -468,6 +486,13 @@ CREATE TABLE m_security_policy ( PRIMARY KEY (oid) ); +CREATE TABLE m_sequence ( + name_norm NVARCHAR(255) COLLATE database_default, + name_orig NVARCHAR(255) COLLATE database_default, + oid NVARCHAR(36) COLLATE database_default NOT NULL, + PRIMARY KEY (oid) +); + CREATE TABLE m_shadow ( attemptNumber INT, dead BIT, @@ -549,7 +574,6 @@ CREATE TABLE m_user ( fullName_orig NVARCHAR(255) COLLATE database_default, givenName_norm NVARCHAR(255) COLLATE database_default, givenName_orig NVARCHAR(255) COLLATE database_default, - hasPhoto BIT NOT NULL, honorificPrefix_norm NVARCHAR(255) COLLATE database_default, honorificPrefix_orig NVARCHAR(255) COLLATE database_default, honorificSuffix_norm NVARCHAR(255) COLLATE database_default, @@ -588,12 +612,6 @@ CREATE TABLE m_user_organizational_unit ( orig NVARCHAR(255) COLLATE database_default ); -CREATE TABLE m_user_photo ( - owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, - photo VARBINARY(MAX), - PRIMARY KEY (owner_oid) -); - CREATE TABLE m_value_policy ( name_norm NVARCHAR(255) COLLATE database_default, name_orig NVARCHAR(255) COLLATE database_default, @@ -613,6 +631,14 @@ CREATE INDEX iAssignmentAdministrative ON m_assignment (administrativeStatus); CREATE INDEX iAssignmentEffective ON m_assignment (effectiveStatus); +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); + +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); + +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); + +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + CREATE INDEX iAExtensionBoolean ON m_assignment_ext_boolean (extensionType, eName, booleanValue); CREATE INDEX iAExtensionDate ON m_assignment_ext_date (extensionType, eName, dateValue); @@ -627,6 +653,8 @@ CREATE INDEX iAExtensionString ON m_assignment_ext_string (extensionType, eName, CREATE INDEX iAssignmentReferenceTargetOid ON m_assignment_reference (targetOid); +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + ALTER TABLE m_connector_host ADD CONSTRAINT uc_connector_host_name UNIQUE (name_norm); @@ -708,6 +736,9 @@ ADD CONSTRAINT uc_role_name UNIQUE (name_norm); ALTER TABLE m_security_policy ADD CONSTRAINT uc_security_policy_name UNIQUE (name_norm); +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + CREATE INDEX iShadowResourceRef ON m_shadow (resourceRef_targetOid); CREATE INDEX iShadowDead ON m_shadow (dead); @@ -820,6 +851,11 @@ ADD CONSTRAINT fk_focus FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + ALTER TABLE m_generic_object ADD CONSTRAINT fk_generic_object FOREIGN KEY (oid) @@ -925,6 +961,11 @@ ADD CONSTRAINT fk_security_policy FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + ALTER TABLE m_shadow ADD CONSTRAINT fk_shadow FOREIGN KEY (oid) @@ -970,11 +1011,6 @@ ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user; -ALTER TABLE m_user_photo -ADD CONSTRAINT fk_user_photo -FOREIGN KEY (owner_oid) -REFERENCES m_user; - ALTER TABLE m_value_policy ADD CONSTRAINT fk_value_policy FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.1.1-3.2.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.1.1-3.2.sql deleted file mode 100644 index fc73f83fb67..00000000000 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.1.1-3.2.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE m_acc_cert_definition ( - name_norm NVARCHAR(255) COLLATE database_default, - name_orig NVARCHAR(255) COLLATE database_default, - oid NVARCHAR(36) COLLATE database_default NOT NULL, - PRIMARY KEY (oid) -); - -CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation NVARCHAR(157) COLLATE database_default, - definitionRef_targetOid NVARCHAR(36) COLLATE database_default, - definitionRef_type INT, - name_norm NVARCHAR(255) COLLATE database_default, - name_orig NVARCHAR(255) COLLATE database_default, - oid NVARCHAR(36) COLLATE database_default NOT NULL, - PRIMARY KEY (oid) -); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT fk_acc_cert_definition - FOREIGN KEY (oid) - REFERENCES m_object; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT fk_acc_cert_campaign - FOREIGN KEY (oid) - REFERENCES m_object; diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.2-3.3.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.2-3.3.sql new file mode 100644 index 00000000000..d5f0ea148ae --- /dev/null +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.2-3.3.sql @@ -0,0 +1,60 @@ +CREATE TABLE m_sequence ( + name_norm NVARCHAR(255) COLLATE database_default, + name_orig NVARCHAR(255) COLLATE database_default, + oid NVARCHAR(36) COLLATE database_default NOT NULL, + PRIMARY KEY (oid) +); + +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + +EXEC sp_rename m_user_photo, m_focus_photo; + +ALTER TABLE m_focus ADD hasPhoto BIT NOT NULL CONSTRAINT default_constraint DEFAULT 0; + +UPDATE m_focus +SET hasPhoto = 0; +UPDATE m_focus +SET hasPhoto = (SELECT hasPhoto + FROM m_user + WHERE m_user.oid = m_focus.oid) +WHERE m_focus.oid IN (SELECT oid + FROM m_user); + +ALTER TABLE m_user DROP COLUMN hasPhoto; + +ALTER TABLE m_focus_photo +DROP CONSTRAINT fk_user_photo; + +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + +ALTER TABLE m_assignment ADD +orgRef_relation NVARCHAR(157) COLLATE database_default, +orgRef_targetOid NVARCHAR(36) COLLATE database_default, +orgRef_type INT, +resourceRef_relation NVARCHAR(157) COLLATE database_default, +resourceRef_targetOid NVARCHAR(36) COLLATE database_default, +resourceRef_type INT; + +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + +ALTER TABLE m_audit_delta ADD +objectName_norm NVARCHAR(255) COLLATE database_default, +objectName_orig NVARCHAR(255) COLLATE database_default, +resourceName_norm NVARCHAR(255) COLLATE database_default, +resourceName_orig NVARCHAR(255) COLLATE database_default, +resourceOid NVARCHAR(36) COLLATE database_default; + From 0d615dcb33dee495128212504fdece76a1290cdf Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 13:42:05 +0100 Subject: [PATCH 034/116] Full and upgrade DB scripts for Oracle. --- ...{oracle-3.2-all.sql => oracle-3.3-all.sql} | 60 ++++++++++--- config/sql/_all/oracle-upgrade-3.1.1-3.2.sql | 32 ------- config/sql/_all/oracle-upgrade-3.2-3.3.sql | 88 ++++++++++--------- .../oracle/{oracle-3.2.sql => oracle-3.3.sql} | 60 ++++++++++--- .../3.3/oracle/oracle-upgrade-3.1.1-3.2.sql | 32 ------- .../3.3/oracle/oracle-upgrade-3.2-3.3.sql | 60 +++++++++++++ 6 files changed, 202 insertions(+), 130 deletions(-) rename config/sql/_all/{oracle-3.2-all.sql => oracle-3.3-all.sql} (97%) delete mode 100644 config/sql/_all/oracle-upgrade-3.1.1-3.2.sql rename config/sql/midpoint/3.3/oracle/{oracle-3.2.sql => oracle-3.3.sql} (95%) delete mode 100644 config/sql/midpoint/3.3/oracle/oracle-upgrade-3.1.1-3.2.sql create mode 100644 config/sql/midpoint/3.3/oracle/oracle-upgrade-3.2-3.3.sql diff --git a/config/sql/_all/oracle-3.2-all.sql b/config/sql/_all/oracle-3.3-all.sql similarity index 97% rename from config/sql/_all/oracle-3.2-all.sql rename to config/sql/_all/oracle-3.3-all.sql index b87217fb1cf..492834906f3 100644 --- a/config/sql/_all/oracle-3.2-all.sql +++ b/config/sql/_all/oracle-3.3-all.sql @@ -50,6 +50,12 @@ CREATE TABLE m_assignment ( modifyChannel VARCHAR2(255 CHAR), modifyTimestamp TIMESTAMP, orderValue NUMBER(10, 0), + orgRef_relation VARCHAR2(157 CHAR), + orgRef_targetOid VARCHAR2(36 CHAR), + orgRef_type NUMBER(10, 0), + resourceRef_relation VARCHAR2(157 CHAR), + resourceRef_targetOid VARCHAR2(36 CHAR), + resourceRef_type NUMBER(10, 0), targetRef_relation VARCHAR2(157 CHAR), targetRef_targetOid VARCHAR2(36 CHAR), targetRef_type NUMBER(10, 0), @@ -165,6 +171,11 @@ CREATE TABLE m_audit_delta ( deltaOid VARCHAR2(36 CHAR), deltaType NUMBER(10, 0), fullResult CLOB, + objectName_norm VARCHAR2(255 CHAR), + objectName_orig VARCHAR2(255 CHAR), + resourceName_norm VARCHAR2(255 CHAR), + resourceName_orig VARCHAR2(255 CHAR), + resourceOid VARCHAR2(36 CHAR), status NUMBER(10, 0), PRIMARY KEY (checksum, record_id) ) INITRANS 30; @@ -243,10 +254,17 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus NUMBER(10, 0), + hasPhoto NUMBER(1, 0) DEFAULT FALSE NOT NULL, oid VARCHAR2(36 CHAR) NOT NULL, PRIMARY KEY (oid) ) INITRANS 30; +CREATE TABLE m_focus_photo ( + owner_oid VARCHAR2(36 CHAR) NOT NULL, + photo BLOB, + PRIMARY KEY (owner_oid) +) INITRANS 30; + CREATE TABLE m_generic_object ( name_norm VARCHAR2(255 CHAR), name_orig VARCHAR2(255 CHAR), @@ -478,6 +496,13 @@ CREATE TABLE m_security_policy ( PRIMARY KEY (oid) ) INITRANS 30; +CREATE TABLE m_sequence ( + name_norm VARCHAR2(255 CHAR), + name_orig VARCHAR2(255 CHAR), + oid VARCHAR2(36 CHAR) NOT NULL, + PRIMARY KEY (oid) +) INITRANS 30; + CREATE TABLE m_shadow ( attemptNumber NUMBER(10, 0), dead NUMBER(1, 0), @@ -559,7 +584,6 @@ CREATE TABLE m_user ( fullName_orig VARCHAR2(255 CHAR), givenName_norm VARCHAR2(255 CHAR), givenName_orig VARCHAR2(255 CHAR), - hasPhoto NUMBER(1, 0) NOT NULL, honorificPrefix_norm VARCHAR2(255 CHAR), honorificPrefix_orig VARCHAR2(255 CHAR), honorificSuffix_norm VARCHAR2(255 CHAR), @@ -598,12 +622,6 @@ CREATE TABLE m_user_organizational_unit ( orig VARCHAR2(255 CHAR) ) INITRANS 30; -CREATE TABLE m_user_photo ( - owner_oid VARCHAR2(36 CHAR) NOT NULL, - photo BLOB, - PRIMARY KEY (owner_oid) -) INITRANS 30; - CREATE TABLE m_value_policy ( name_norm VARCHAR2(255 CHAR), name_orig VARCHAR2(255 CHAR), @@ -623,6 +641,14 @@ CREATE INDEX iAssignmentAdministrative ON m_assignment (administrativeStatus) IN CREATE INDEX iAssignmentEffective ON m_assignment (effectiveStatus) INITRANS 30; +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid) INITRANS 30; + +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid) INITRANS 30; + +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid) INITRANS 30; + +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid) INITRANS 30; + CREATE INDEX iAExtensionBoolean ON m_assignment_ext_boolean (extensionType, eName, booleanValue) INITRANS 30; CREATE INDEX iAExtensionDate ON m_assignment_ext_date (extensionType, eName, dateValue) INITRANS 30; @@ -637,6 +663,8 @@ CREATE INDEX iAExtensionString ON m_assignment_ext_string (extensionType, eName, CREATE INDEX iAssignmentReferenceTargetOid ON m_assignment_reference (targetOid) INITRANS 30; +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue) INITRANS 30; + ALTER TABLE m_connector_host ADD CONSTRAINT uc_connector_host_name UNIQUE (name_norm) INITRANS 30; @@ -718,6 +746,9 @@ ADD CONSTRAINT uc_role_name UNIQUE (name_norm) INITRANS 30; ALTER TABLE m_security_policy ADD CONSTRAINT uc_security_policy_name UNIQUE (name_norm) INITRANS 30; +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm) INITRANS 30; + CREATE INDEX iShadowResourceRef ON m_shadow (resourceRef_targetOid) INITRANS 30; CREATE INDEX iShadowDead ON m_shadow (dead) INITRANS 30; @@ -830,6 +861,11 @@ ADD CONSTRAINT fk_focus FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + ALTER TABLE m_generic_object ADD CONSTRAINT fk_generic_object FOREIGN KEY (oid) @@ -935,6 +971,11 @@ ADD CONSTRAINT fk_security_policy FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + ALTER TABLE m_shadow ADD CONSTRAINT fk_shadow FOREIGN KEY (oid) @@ -980,11 +1021,6 @@ ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user; -ALTER TABLE m_user_photo -ADD CONSTRAINT fk_user_photo -FOREIGN KEY (owner_oid) -REFERENCES m_user; - ALTER TABLE m_value_policy ADD CONSTRAINT fk_value_policy FOREIGN KEY (oid) diff --git a/config/sql/_all/oracle-upgrade-3.1.1-3.2.sql b/config/sql/_all/oracle-upgrade-3.1.1-3.2.sql deleted file mode 100644 index a43efd9f6e3..00000000000 --- a/config/sql/_all/oracle-upgrade-3.1.1-3.2.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR2(255 CHAR), - name_orig VARCHAR2(255 CHAR), - oid VARCHAR2(36 CHAR) NOT NULL, - PRIMARY KEY (oid) -) INITRANS 30; - -CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR2(157 CHAR), - definitionRef_targetOid VARCHAR2(36 CHAR), - definitionRef_type NUMBER(10,0), - name_norm VARCHAR2(255 CHAR), - name_orig VARCHAR2(255 CHAR), - oid VARCHAR2(36 CHAR) NOT NULL, - PRIMARY KEY (oid) -) INITRANS 30; - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm) INITRANS 30; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm) INITRANS 30; - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT fk_acc_cert_definition - FOREIGN KEY (oid) - REFERENCES m_object; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT fk_acc_cert_campaign - FOREIGN KEY (oid) - REFERENCES m_object; diff --git a/config/sql/_all/oracle-upgrade-3.2-3.3.sql b/config/sql/_all/oracle-upgrade-3.2-3.3.sql index 84edd1cec10..1d55df77366 100644 --- a/config/sql/_all/oracle-upgrade-3.2-3.3.sql +++ b/config/sql/_all/oracle-upgrade-3.2-3.3.sql @@ -1,56 +1,60 @@ -create table m_sequence ( - name_norm varchar2(255 char), - name_orig varchar2(255 char), - oid varchar2(36 char) not null, - primary key (oid) +CREATE TABLE m_sequence ( + name_norm VARCHAR2(255 CHAR), + name_orig VARCHAR2(255 CHAR), + oid VARCHAR2(36 CHAR) NOT NULL, + PRIMARY KEY (oid) ); -alter table m_sequence - add constraint uc_sequence_name unique (name_norm); +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); -alter table m_sequence - add constraint fk_sequence - foreign key (oid) - references m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; +ALTER TABLE m_user_photo +DROP CONSTRAINT fk_user_photo; -alter table m_user_photo - drop constraint fk_user_photo; +RENAME m_user_photo TO m_focus_photo; -rename m_user_photo to m_focus_photo; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; -alter table m_focus_photo - add constraint fk_focus_photo - foreign key (owner_oid) - references m_focus; +ALTER TABLE m_focus ADD hasPhoto NUMBER(1, 0) DEFAULT 0 NOT NULL; +UPDATE m_focus +SET hasPhoto = 0; +UPDATE m_focus +SET hasPhoto = (SELECT hasPhoto + FROM m_user + WHERE m_user.oid = m_focus.oid) +WHERE m_focus.oid IN (SELECT oid + FROM m_user); -alter table m_focus add hasPhoto number(1,0) default 0 not null; -update m_focus set hasPhoto = 0; -update m_focus set hasPhoto = (select hasPhoto from m_user where m_user.oid = m_focus.oid) - where m_focus.oid in (select oid from m_user); +ALTER TABLE m_user DROP COLUMN hasPhoto; -alter table m_user drop column hasPhoto; +ALTER TABLE m_assignment ADD ( +orgRef_relation VARCHAR2(157 CHAR), +orgRef_targetOid VARCHAR2(36 CHAR), +orgRef_type NUMBER(10, 0), +resourceRef_relation VARCHAR2(157 CHAR), +resourceRef_targetOid VARCHAR2(36 CHAR), +resourceRef_type NUMBER(10, 0)); -alter table m_assignment add ( - orgRef_relation varchar2(157 char), - orgRef_targetOid varchar2(36 char), - orgRef_type number(10,0), - resourceRef_relation varchar2(157 char), - resourceRef_targetOid varchar2(36 char), - resourceRef_type number(10,0)); +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); -create index iTargetRefTargetOid on m_assignment (targetRef_targetOid); -create index iTenantRefTargetOid on m_assignment (tenantRef_targetOid); -create index iOrgRefTargetOid on m_assignment (orgRef_targetOid); -create index iResourceRefTargetOid on m_assignment (resourceRef_targetOid); +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); -create index iTimestampValue on m_audit_event (timestampValue); - -alter table m_audit_delta add ( - objectName_norm varchar2(255 char), - objectName_orig varchar2(255 char), - resourceName_norm varchar2(255 char), - resourceName_orig varchar2(255 char), - resourceOid varchar2(36 char)); +ALTER TABLE m_audit_delta ADD ( +objectName_norm VARCHAR2(255 CHAR), +objectName_orig VARCHAR2(255 CHAR), +resourceName_norm VARCHAR2(255 CHAR), +resourceName_orig VARCHAR2(255 CHAR), +resourceOid VARCHAR2(36 CHAR)); diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.2.sql b/config/sql/midpoint/3.3/oracle/oracle-3.3.sql similarity index 95% rename from config/sql/midpoint/3.3/oracle/oracle-3.2.sql rename to config/sql/midpoint/3.3/oracle/oracle-3.3.sql index fec723a5c83..e2be7e3e7a7 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.2.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.3.sql @@ -50,6 +50,12 @@ CREATE TABLE m_assignment ( modifyChannel VARCHAR2(255 CHAR), modifyTimestamp TIMESTAMP, orderValue NUMBER(10, 0), + orgRef_relation VARCHAR2(157 CHAR), + orgRef_targetOid VARCHAR2(36 CHAR), + orgRef_type NUMBER(10, 0), + resourceRef_relation VARCHAR2(157 CHAR), + resourceRef_targetOid VARCHAR2(36 CHAR), + resourceRef_type NUMBER(10, 0), targetRef_relation VARCHAR2(157 CHAR), targetRef_targetOid VARCHAR2(36 CHAR), targetRef_type NUMBER(10, 0), @@ -165,6 +171,11 @@ CREATE TABLE m_audit_delta ( deltaOid VARCHAR2(36 CHAR), deltaType NUMBER(10, 0), fullResult CLOB, + objectName_norm VARCHAR2(255 CHAR), + objectName_orig VARCHAR2(255 CHAR), + resourceName_norm VARCHAR2(255 CHAR), + resourceName_orig VARCHAR2(255 CHAR), + resourceOid VARCHAR2(36 CHAR), status NUMBER(10, 0), PRIMARY KEY (checksum, record_id) ) INITRANS 30; @@ -243,10 +254,17 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus NUMBER(10, 0), + hasPhoto NUMBER(1, 0) DEFAULT FALSE NOT NULL, oid VARCHAR2(36 CHAR) NOT NULL, PRIMARY KEY (oid) ) INITRANS 30; +CREATE TABLE m_focus_photo ( + owner_oid VARCHAR2(36 CHAR) NOT NULL, + photo BLOB, + PRIMARY KEY (owner_oid) +) INITRANS 30; + CREATE TABLE m_generic_object ( name_norm VARCHAR2(255 CHAR), name_orig VARCHAR2(255 CHAR), @@ -478,6 +496,13 @@ CREATE TABLE m_security_policy ( PRIMARY KEY (oid) ) INITRANS 30; +CREATE TABLE m_sequence ( + name_norm VARCHAR2(255 CHAR), + name_orig VARCHAR2(255 CHAR), + oid VARCHAR2(36 CHAR) NOT NULL, + PRIMARY KEY (oid) +) INITRANS 30; + CREATE TABLE m_shadow ( attemptNumber NUMBER(10, 0), dead NUMBER(1, 0), @@ -559,7 +584,6 @@ CREATE TABLE m_user ( fullName_orig VARCHAR2(255 CHAR), givenName_norm VARCHAR2(255 CHAR), givenName_orig VARCHAR2(255 CHAR), - hasPhoto NUMBER(1, 0) NOT NULL, honorificPrefix_norm VARCHAR2(255 CHAR), honorificPrefix_orig VARCHAR2(255 CHAR), honorificSuffix_norm VARCHAR2(255 CHAR), @@ -598,12 +622,6 @@ CREATE TABLE m_user_organizational_unit ( orig VARCHAR2(255 CHAR) ) INITRANS 30; -CREATE TABLE m_user_photo ( - owner_oid VARCHAR2(36 CHAR) NOT NULL, - photo BLOB, - PRIMARY KEY (owner_oid) -) INITRANS 30; - CREATE TABLE m_value_policy ( name_norm VARCHAR2(255 CHAR), name_orig VARCHAR2(255 CHAR), @@ -623,6 +641,14 @@ CREATE INDEX iAssignmentAdministrative ON m_assignment (administrativeStatus) IN CREATE INDEX iAssignmentEffective ON m_assignment (effectiveStatus) INITRANS 30; +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid) INITRANS 30; + +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid) INITRANS 30; + +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid) INITRANS 30; + +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid) INITRANS 30; + CREATE INDEX iAExtensionBoolean ON m_assignment_ext_boolean (extensionType, eName, booleanValue) INITRANS 30; CREATE INDEX iAExtensionDate ON m_assignment_ext_date (extensionType, eName, dateValue) INITRANS 30; @@ -637,6 +663,8 @@ CREATE INDEX iAExtensionString ON m_assignment_ext_string (extensionType, eName, CREATE INDEX iAssignmentReferenceTargetOid ON m_assignment_reference (targetOid) INITRANS 30; +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue) INITRANS 30; + ALTER TABLE m_connector_host ADD CONSTRAINT uc_connector_host_name UNIQUE (name_norm) INITRANS 30; @@ -718,6 +746,9 @@ ADD CONSTRAINT uc_role_name UNIQUE (name_norm) INITRANS 30; ALTER TABLE m_security_policy ADD CONSTRAINT uc_security_policy_name UNIQUE (name_norm) INITRANS 30; +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm) INITRANS 30; + CREATE INDEX iShadowResourceRef ON m_shadow (resourceRef_targetOid) INITRANS 30; CREATE INDEX iShadowDead ON m_shadow (dead) INITRANS 30; @@ -830,6 +861,11 @@ ADD CONSTRAINT fk_focus FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + ALTER TABLE m_generic_object ADD CONSTRAINT fk_generic_object FOREIGN KEY (oid) @@ -935,6 +971,11 @@ ADD CONSTRAINT fk_security_policy FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + ALTER TABLE m_shadow ADD CONSTRAINT fk_shadow FOREIGN KEY (oid) @@ -980,11 +1021,6 @@ ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user; -ALTER TABLE m_user_photo -ADD CONSTRAINT fk_user_photo -FOREIGN KEY (owner_oid) -REFERENCES m_user; - ALTER TABLE m_value_policy ADD CONSTRAINT fk_value_policy FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.1.1-3.2.sql b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.1.1-3.2.sql deleted file mode 100644 index a43efd9f6e3..00000000000 --- a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.1.1-3.2.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR2(255 CHAR), - name_orig VARCHAR2(255 CHAR), - oid VARCHAR2(36 CHAR) NOT NULL, - PRIMARY KEY (oid) -) INITRANS 30; - -CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR2(157 CHAR), - definitionRef_targetOid VARCHAR2(36 CHAR), - definitionRef_type NUMBER(10,0), - name_norm VARCHAR2(255 CHAR), - name_orig VARCHAR2(255 CHAR), - oid VARCHAR2(36 CHAR) NOT NULL, - PRIMARY KEY (oid) -) INITRANS 30; - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm) INITRANS 30; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm) INITRANS 30; - -ALTER TABLE m_acc_cert_definition - ADD CONSTRAINT fk_acc_cert_definition - FOREIGN KEY (oid) - REFERENCES m_object; - -ALTER TABLE m_acc_cert_campaign - ADD CONSTRAINT fk_acc_cert_campaign - FOREIGN KEY (oid) - REFERENCES m_object; diff --git a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.2-3.3.sql b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.2-3.3.sql new file mode 100644 index 00000000000..1d55df77366 --- /dev/null +++ b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.2-3.3.sql @@ -0,0 +1,60 @@ +CREATE TABLE m_sequence ( + name_norm VARCHAR2(255 CHAR), + name_orig VARCHAR2(255 CHAR), + oid VARCHAR2(36 CHAR) NOT NULL, + PRIMARY KEY (oid) +); + +ALTER TABLE m_sequence +ADD CONSTRAINT uc_sequence_name UNIQUE (name_norm); + +ALTER TABLE m_sequence +ADD CONSTRAINT fk_sequence +FOREIGN KEY (oid) +REFERENCES m_object; + + +ALTER TABLE m_user_photo +DROP CONSTRAINT fk_user_photo; + +RENAME m_user_photo TO m_focus_photo; + +ALTER TABLE m_focus_photo +ADD CONSTRAINT fk_focus_photo +FOREIGN KEY (owner_oid) +REFERENCES m_focus; + +ALTER TABLE m_focus ADD hasPhoto NUMBER(1, 0) DEFAULT 0 NOT NULL; +UPDATE m_focus +SET hasPhoto = 0; +UPDATE m_focus +SET hasPhoto = (SELECT hasPhoto + FROM m_user + WHERE m_user.oid = m_focus.oid) +WHERE m_focus.oid IN (SELECT oid + FROM m_user); + +ALTER TABLE m_user DROP COLUMN hasPhoto; + + +ALTER TABLE m_assignment ADD ( +orgRef_relation VARCHAR2(157 CHAR), +orgRef_targetOid VARCHAR2(36 CHAR), +orgRef_type NUMBER(10, 0), +resourceRef_relation VARCHAR2(157 CHAR), +resourceRef_targetOid VARCHAR2(36 CHAR), +resourceRef_type NUMBER(10, 0)); + +CREATE INDEX iTargetRefTargetOid ON m_assignment (targetRef_targetOid); +CREATE INDEX iTenantRefTargetOid ON m_assignment (tenantRef_targetOid); +CREATE INDEX iOrgRefTargetOid ON m_assignment (orgRef_targetOid); +CREATE INDEX iResourceRefTargetOid ON m_assignment (resourceRef_targetOid); + +CREATE INDEX iTimestampValue ON m_audit_event (timestampValue); + +ALTER TABLE m_audit_delta ADD ( +objectName_norm VARCHAR2(255 CHAR), +objectName_orig VARCHAR2(255 CHAR), +resourceName_norm VARCHAR2(255 CHAR), +resourceName_orig VARCHAR2(255 CHAR), +resourceOid VARCHAR2(36 CHAR)); From fcc789bc93ef4010c34254e65d65ec64297a88b8 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 13:46:49 +0100 Subject: [PATCH 035/116] Fixing problem in script for SQL server. --- config/sql/_all/sqlserver-3.3-all.sql | 2 +- config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/sql/_all/sqlserver-3.3-all.sql b/config/sql/_all/sqlserver-3.3-all.sql index 31fb052f1cf..af67a1d1f86 100644 --- a/config/sql/_all/sqlserver-3.3-all.sql +++ b/config/sql/_all/sqlserver-3.3-all.sql @@ -251,7 +251,7 @@ CREATE TABLE m_focus ( validTo DATETIME2, validityChangeTimestamp DATETIME2, validityStatus INT, - hasPhoto BIT DEFAULT FALSE NOT NULL, + hasPhoto BIT DEFAULT 0 NOT NULL, oid NVARCHAR(36) COLLATE database_default NOT NULL, PRIMARY KEY (oid) ); diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql index c05f068cb0e..b6afb8095b2 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql @@ -251,7 +251,7 @@ CREATE TABLE m_focus ( validTo DATETIME2, validityChangeTimestamp DATETIME2, validityStatus INT, - hasPhoto BIT DEFAULT FALSE NOT NULL, + hasPhoto BIT DEFAULT 0 NOT NULL, oid NVARCHAR(36) COLLATE database_default NOT NULL, PRIMARY KEY (oid) ); From 3f27a3978ad7d96f2fda69f2086fb73d7332ff6d Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 14:05:19 +0100 Subject: [PATCH 036/116] Fixing the same problem in script for Oracle. --- config/sql/_all/oracle-3.3-all.sql | 2 +- config/sql/midpoint/3.3/oracle/oracle-3.3.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/sql/_all/oracle-3.3-all.sql b/config/sql/_all/oracle-3.3-all.sql index 492834906f3..6705f3dea6b 100644 --- a/config/sql/_all/oracle-3.3-all.sql +++ b/config/sql/_all/oracle-3.3-all.sql @@ -254,7 +254,7 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus NUMBER(10, 0), - hasPhoto NUMBER(1, 0) DEFAULT FALSE NOT NULL, + hasPhoto NUMBER(1, 0) DEFAULT 0 NOT NULL, oid VARCHAR2(36 CHAR) NOT NULL, PRIMARY KEY (oid) ) INITRANS 30; diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.3.sql b/config/sql/midpoint/3.3/oracle/oracle-3.3.sql index e2be7e3e7a7..67435c2acfb 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.3.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.3.sql @@ -254,7 +254,7 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus NUMBER(10, 0), - hasPhoto NUMBER(1, 0) DEFAULT FALSE NOT NULL, + hasPhoto NUMBER(1, 0) DEFAULT 0 NOT NULL, oid VARCHAR2(36 CHAR) NOT NULL, PRIMARY KEY (oid) ) INITRANS 30; From e788289988cfb4ff3c76a1664201252fd029aace Mon Sep 17 00:00:00 2001 From: honchar Date: Mon, 30 Nov 2015 14:12:21 +0100 Subject: [PATCH 037/116] MID-2587 string resources are fixed for resource wizard --- .../src/main/resources/localization/Midpoint.properties | 5 +++-- .../main/resources/localization/Midpoint_en_US.properties | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index 7294aae9ac8..3d96d5ee962 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -112,6 +112,7 @@ associationAttribute.nullValid=Choose One AsyncDashboardPanel.loading=Loading data AttributeFetchStrategyType.EXPLICIT=Explicit AttributeFetchStrategyType.IMPLICIT=Implicit +AttributeFetchStrategyType.MINIMAL=Minimal AuditEventStageType.EXECUTION=Execution AuditEventStageType.REQUEST=Request AuditEventType.ADD_OBJECT=Add object @@ -370,8 +371,8 @@ HandlerUriActions.ACTION_DELETE_SHADOW=Delete shadow HandlerUriActions.ACTION_DELETE_USER=Delete user HandlerUriActions.ACTION_DISABLE_ACCOUNT=Disable account HandlerUriActions.ACTION_DISABLE_USER=Disable user -HandlerUriActions.ACTION_INACTIVE_FOCUS=Inactive focus -HandlerUriActions.ACTION_INACTIVE_SHADOW=Inactive shadow +HandlerUriActions.ACTION_INACTIVATE_FOCUS=Inactivate focus +HandlerUriActions.ACTION_INACTIVATE_SHADOW=Inactivate shadow HandlerUriActions.ACTION_LINK_ACCOUNT=Link account HandlerUriActions.ACTION_LINK=Link HandlerUriActions.ACTION_MODIFY_PASSWORD=Modify password diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties b/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties index f3abcc38324..ef70132d9ec 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties @@ -112,6 +112,7 @@ associationAttribute.nullValid=Choose One AsyncDashboardPanel.loading=Loading data AttributeFetchStrategyType.EXPLICIT=Explicit AttributeFetchStrategyType.IMPLICIT=Implicit +AttributeFetchStrategyType.MINIMAL=Minimal AuditEventStageType.EXECUTION=Execution AuditEventStageType.REQUEST=Request AuditEventType.ADD_OBJECT=Add object @@ -370,8 +371,8 @@ HandlerUriActions.ACTION_DELETE_SHADOW=Delete shadow HandlerUriActions.ACTION_DELETE_USER=Delete user HandlerUriActions.ACTION_DISABLE_ACCOUNT=Disable account HandlerUriActions.ACTION_DISABLE_USER=Disable user -HandlerUriActions.ACTION_INACTIVE_FOCUS=Inactive focus -HandlerUriActions.ACTION_INACTIVE_SHADOW=Inactive shadow +HandlerUriActions.ACTION_INACTIVATE_FOCUS=Inactivate focus +HandlerUriActions.ACTION_INACTIVATE_SHADOW=Inactivate shadow HandlerUriActions.ACTION_LINK_ACCOUNT=Link account HandlerUriActions.ACTION_LINK=Link HandlerUriActions.ACTION_MODIFY_PASSWORD=Modify password From 8c53a4ca761c157a7fd57ceaea1b9269f7241492 Mon Sep 17 00:00:00 2001 From: honchar Date: Mon, 30 Nov 2015 14:58:39 +0100 Subject: [PATCH 038/116] MID-2737 Resource wizard ->step Schema -> Xml tab -> XmlEditorPanel is made disabled for editing --- .../web/component/wizard/resource/SchemaStep.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaStep.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaStep.java index 12da6911fd2..cad42e0516f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaStep.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaStep.java @@ -25,6 +25,7 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.AceEditor; import com.evolveum.midpoint.web.component.AjaxButton; import com.evolveum.midpoint.web.component.TabbedPanel; import com.evolveum.midpoint.web.component.wizard.WizardStep; @@ -57,6 +58,7 @@ public class SchemaStep extends WizardStep { private static final String ID_TAB_PANEL = "tabPanel"; private static final String ID_RELOAD = "reload"; + private static final String ID_ACE_EDITOR = "aceEditor"; private IModel> model; public SchemaStep(IModel> model, PageBase pageBase) { @@ -172,7 +174,13 @@ private ITab createSchemaEditor() { @Override public WebMarkupContainer getPanel(String panelId) { - return new XmlEditorPanel(panelId, createXmlEditorModel()); + XmlEditorPanel xmlEditorPanel = new XmlEditorPanel(panelId, createXmlEditorModel()); + // quick fix: now changes from XmlEditorPanel are not saved anyhow + //(e.g. by clicking Finish button in wizard). For now, + //panel is made disabled for editing + AceEditor aceEditor = (AceEditor) xmlEditorPanel.get(ID_ACE_EDITOR); + aceEditor.setReadonly(true); + return xmlEditorPanel; } }; } From 2e92e0062e3d96b1a35704b68b034f2e68d6676d Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 19:23:48 +0100 Subject: [PATCH 039/116] Attempt to add certification decision to repo. --- .../xml/ns/public/common/common-3.xsd | 1 + .../data/common/container/L2Container.java | 45 ++++ .../container/RAccessCertificationCase.java | 73 +++++-- .../RAccessCertificationDecision.java | 194 ++++++++++++++++++ .../enums/RAccessCertificationResponse.java | 51 +++++ .../sql/data/common/id/RL2ContainerId.java | 92 +++++++++ .../sql/query2/definition/NotQueryable.java | 3 + .../repo/sql/util/ContainerIdGenerator.java | 35 +++- 8 files changed, 470 insertions(+), 24 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/L2Container.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationResponse.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 57926b57aa6..a12eaea2f70 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -12851,6 +12851,7 @@ + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/L2Container.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/L2Container.java new file mode 100644 index 00000000000..0cdc8884324 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/L2Container.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2013 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.container; + +import com.evolveum.midpoint.repo.sql.util.EntityState; + +import java.io.Serializable; + +/** + * "Level 2 container" = container in container in object + * + * @author mederly + */ +public interface L2Container extends EntityState, Serializable { + + T getOwner(); + + String getOwnerOwnerOid(); + + Integer getOwnerId(); + + Integer getId(); + + void setOwner(T owner); + + void setOwnerOwnerOid(String ownerOwnerOid); + + void setOwnerId(Integer id); + + void setId(Integer id); +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 35b7ccd7491..76436561a55 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; +import com.evolveum.midpoint.repo.sql.data.common.enums.RAccessCertificationResponse; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; @@ -32,7 +33,9 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Where; @@ -90,8 +93,9 @@ public class RAccessCertificationCase implements Container { private XMLGregorianCalendar reviewRequestedTimestamp; private XMLGregorianCalendar reviewDeadline; private XMLGregorianCalendar remediedTimestamp; - // TODO: private Set decisions; - // TODO: currentResponse, currentResponseStage + private Set decisions; + private RAccessCertificationResponse currentResponse; + private Integer currentResponseStage; public RAccessCertificationCase() { this(null); @@ -153,6 +157,7 @@ public REmbeddedReference getObjectRef() { return objectRef; } + @Deprecated // probably will be replaced by query "case.currentResponseStage = campaign.currentStage" @Column(name = "case_enabled") public boolean isEnabled() { return enabled; @@ -170,6 +175,24 @@ public XMLGregorianCalendar getRemediedTimestamp() { return remediedTimestamp; } + @OneToMany(mappedBy = RAccessCertificationDecision.F_OWNER, orphanRemoval = true) + @ForeignKey(name = "none") + @Cascade({org.hibernate.annotations.CascadeType.ALL}) + public Set getDecisions() { + if (decisions == null) { + decisions = new HashSet<>(); + } + return decisions; + } + + public RAccessCertificationResponse getCurrentResponse() { + return currentResponse; + } + + public Integer getCurrentResponseStage() { + return currentResponseStage; + } + public void setOwner(RObject owner) { this.owner = owner; } @@ -206,6 +229,18 @@ public void setRemediedTimestamp(XMLGregorianCalendar remediedTimestamp) { this.remediedTimestamp = remediedTimestamp; } + public void setDecisions(Set decisions) { + this.decisions = decisions; + } + + public void setCurrentResponse(RAccessCertificationResponse currentResponse) { + this.currentResponse = currentResponse; + } + + public void setCurrentResponseStage(Integer currentResponseStage) { + this.currentResponseStage = currentResponseStage; + } + @Lob public byte[] getFullObject() { return fullObject; @@ -233,7 +268,12 @@ public boolean equals(Object o) { return false; if (reviewDeadline != null ? !reviewDeadline.equals(that.reviewDeadline) : that.reviewDeadline != null) return false; - return !(remediedTimestamp != null ? !remediedTimestamp.equals(that.remediedTimestamp) : that.remediedTimestamp != null); + if (remediedTimestamp != null ? !remediedTimestamp.equals(that.remediedTimestamp) : that.remediedTimestamp != null) + return false; + if (decisions != null ? !decisions.equals(that.decisions) : that.decisions != null) return false; + if (currentResponse != that.currentResponse) return false; + return !(currentResponseStage != null ? !currentResponseStage.equals(that.currentResponseStage) : that.currentResponseStage != null); + } @Override @@ -247,27 +287,11 @@ public int hashCode() { result = 31 * result + (reviewRequestedTimestamp != null ? reviewRequestedTimestamp.hashCode() : 0); result = 31 * result + (reviewDeadline != null ? reviewDeadline.hashCode() : 0); result = 31 * result + (remediedTimestamp != null ? remediedTimestamp.hashCode() : 0); + result = 31 * result + (currentResponse != null ? currentResponse.hashCode() : 0); + result = 31 * result + (currentResponseStage != null ? currentResponseStage.hashCode() : 0); return result; } -// public static void copyFromJAXB(AccessCertificationCaseType jaxb, RAccessCertificationCase repo, ObjectType parent, PrismContext prismContext, -// IdGeneratorResult generatorResult) throws DtoTranslationException { -// Validate.notNull(repo, "Repo object must not be null."); -// Validate.notNull(jaxb, "JAXB object must not be null."); -// -// repo.setOwnerOid(parent.getOid()); -// repo.setId(RUtil.toInteger(jaxb.getId())); -// -// repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getTargetRef(), prismContext)); -// repo.setTargetRef(RUtil.jaxbRefToEmbeddedNamedRepoRef(jaxb.getObjectRef(), prismContext)); -// repo.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( -// jaxb.getReviewerRef(), prismContext, repo, RCReferenceOwner.CASE_REVIEWER)); -// repo.setEnabled(BooleanUtils.isTrue(jaxb.isEnabled())); -// repo.setReviewRequestedTimestamp(jaxb.getReviewRequestedTimestamp()); -// repo.setReviewDeadline(jaxb.getReviewDeadline()); -// repo.setRemediedTimestamp(jaxb.getRemediedTimestamp()); -// } - @Override public String toString() { return "RAccessCertificationCase{" + @@ -313,6 +337,13 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 rCase.setReviewRequestedTimestamp(case1.getReviewRequestedTimestamp()); rCase.setReviewDeadline(case1.getReviewDeadline()); rCase.setRemediedTimestamp(case1.getRemediedTimestamp()); + rCase.setCurrentResponse(RUtil.getRepoEnumValue(case1.getCurrentResponse(), RAccessCertificationResponse.class)); + rCase.setCurrentResponseStage(case1.getCurrentResponseStage()); + for (AccessCertificationDecisionType decision : case1.getDecision()) { + RAccessCertificationDecision rDecision = RAccessCertificationDecision.toRepo(rCase, decision, prismContext); + rCase.getDecisions().add(rDecision); + } + PrismContainerValue cvalue = case1.asPrismContainerValue(); String xml; try { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java new file mode 100644 index 00000000000..2736dd44e9a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.container; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; +import com.evolveum.midpoint.repo.sql.data.common.enums.RAccessCertificationResponse; +import com.evolveum.midpoint.repo.sql.data.common.id.RL2ContainerId; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * Although being an image of a Containerable, this class is not a container in the sense of Container class: + * its owner is not a RObject. + * + * @author mederly + */ + +@JaxbType(type = AccessCertificationDecisionType.class) +@Entity +@IdClass(RL2ContainerId.class) +@Table(name = "m_acc_cert_decision", indexes = { +// @Index(name = "iObjectRefTargetOid", columnList = "objectRef_targetOid"), +// @Index(name = "iTargetRefTargetOid", columnList = "targetRef_targetOid") +}) +public class RAccessCertificationDecision implements L2Container { + + private static final Trace LOGGER = TraceManager.getTrace(RAccessCertificationDecision.class); + + public static final String F_OWNER = "owner"; + + private Boolean trans; + + private RAccessCertificationCase owner; + private String ownerOwnerOid; + private Integer ownerId; + private Integer id; + + private int stageNumber; + private REmbeddedReference reviewerRef; + private RAccessCertificationResponse response; + private String comment; + private XMLGregorianCalendar timestamp; + + public RAccessCertificationDecision() { + } + + @Id + //@org.hibernate.annotations.ForeignKey(name = "fk_ac_case_owner") + @ManyToOne(fetch = FetchType.LAZY) + @MapsId("owner") + @NotQueryable + public RAccessCertificationCase getOwner() { + return owner; + } + + @Column(name = "owner_owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + @NotQueryable + public String getOwnerOwnerOid() { + if (owner != null && ownerOwnerOid == null) { + ownerOwnerOid = owner.getOwnerOid(); + } + return ownerOwnerOid; + } + + @Id + @NotQueryable + @Column(name = "owner_id") + public Integer getOwnerId() { + return ownerId; + } + + @Id + @GeneratedValue(generator = "ContainerIdGenerator") + @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") + @Column(name = "id") + @NotQueryable + public Integer getId() { + return id; + } + + public int getStageNumber() { + return stageNumber; + } + + @Embedded + public REmbeddedReference getReviewerRef() { + return reviewerRef; + } + + public RAccessCertificationResponse getResponse() { + return response; + } + + public String getComment() { + return comment; + } + + public XMLGregorianCalendar getTimestamp() { + return timestamp; + } + + public void setOwner(RAccessCertificationCase owner) { + this.owner = owner; + } + + public void setOwnerOwnerOid(String campaignOid) { + this.ownerOwnerOid = campaignOid; + } + + public void setOwnerId(Integer caseId) { + this.ownerId = caseId; + } + + public void setId(Integer id) { + this.id = id; + } + + public void setStageNumber(int stageNumber) { + this.stageNumber = stageNumber; + } + + public void setReviewerRef(REmbeddedReference reviewerRef) { + this.reviewerRef = reviewerRef; + } + + public void setResponse(RAccessCertificationResponse response) { + this.response = response; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public void setTimestamp(XMLGregorianCalendar timestamp) { + this.timestamp = timestamp; + } + + @Transient + public Boolean isTransient() { + return trans; + } + + public void setTransient(Boolean trans) { + this.trans = trans; + } + + public static RAccessCertificationDecision toRepo(RAccessCertificationCase owningCase, AccessCertificationDecisionType decision, PrismContext prismContext) { + RAccessCertificationDecision rDecision = toRepo(decision, prismContext); + rDecision.setOwner(owningCase); + return rDecision; + } + + public static RAccessCertificationDecision toRepo(String campaignOid, int caseId, AccessCertificationDecisionType decision, PrismContext prismContext) { + RAccessCertificationDecision rCase = toRepo(decision, prismContext); + rCase.setOwnerOwnerOid(campaignOid); + rCase.setOwnerId(caseId); + return rCase; + } + + private static RAccessCertificationDecision toRepo(AccessCertificationDecisionType decision, PrismContext prismContext) { + RAccessCertificationDecision rDecision = new RAccessCertificationDecision(); + rDecision.setId(RUtil.toInteger(decision.getId())); + rDecision.setStageNumber(decision.getStageNumber()); + rDecision.setReviewerRef(RUtil.jaxbRefToEmbeddedRepoRef(decision.getReviewerRef(), prismContext)); + rDecision.setResponse(RUtil.getRepoEnumValue(decision.getResponse(), RAccessCertificationResponse.class)); + rDecision.setComment(decision.getComment()); + rDecision.setTimestamp(decision.getTimestamp()); + return rDecision; + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationResponse.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationResponse.java new file mode 100644 index 00000000000..8a417075a6e --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationResponse.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2013 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.enums; + +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; + +/** + * @author mederly + */ +@JaxbType(type = AccessCertificationResponseType.class) +public enum RAccessCertificationResponse implements SchemaEnum { + + ACCEPT(AccessCertificationResponseType.ACCEPT), + + REVOKE(AccessCertificationResponseType.REVOKE), + + REDUCE(AccessCertificationResponseType.REDUCE), + + NOT_DECIDED(AccessCertificationResponseType.NOT_DECIDED), + + DELEGATE(AccessCertificationResponseType.DELEGATE), + + NO_RESPONSE(AccessCertificationResponseType.NO_RESPONSE); + + private AccessCertificationResponseType status; + + private RAccessCertificationResponse(AccessCertificationResponseType status) { + this.status = status; + } + + @Override + public AccessCertificationResponseType getSchemaValue() { + return status; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java new file mode 100644 index 00000000000..95a56b19590 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2010-2013 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.id; + +import java.io.Serializable; + +/** + * ID for second-level container (container within container within object). + * + * @author mederly + */ +public class RL2ContainerId implements Serializable { + + private String ownerOwnerOid; + private Integer ownerId; + private Integer id; + + public RL2ContainerId(String ownerOwnerOid, Integer ownerId, Integer id) { + this.ownerOwnerOid = ownerOwnerOid; + this.ownerId = ownerId; + this.id = id; + } + + public String getOwnerOwnerOid() { + return ownerOwnerOid; + } + + public void setOwnerOwnerOid(String ownerOwnerOid) { + this.ownerOwnerOid = ownerOwnerOid; + } + + public Integer getOwnerId() { + return ownerId; + } + + public void setOwnerId(Integer ownerId) { + this.ownerId = ownerId; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RL2ContainerId)) return false; + + RL2ContainerId that = (RL2ContainerId) o; + + if (ownerOwnerOid != null ? !ownerOwnerOid.equals(that.ownerOwnerOid) : that.ownerOwnerOid != null) + return false; + if (ownerId != null ? !ownerId.equals(that.ownerId) : that.ownerId != null) return false; + return !(id != null ? !id.equals(that.id) : that.id != null); + + } + + @Override + public int hashCode() { + int result = ownerOwnerOid != null ? ownerOwnerOid.hashCode() : 0; + result = 31 * result + (ownerId != null ? ownerId.hashCode() : 0); + result = 31 * result + (id != null ? id.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "RL2ContainerId{" + + "ownerOwnerOid='" + ownerOwnerOid + '\'' + + ", ownerId=" + ownerId + + ", id=" + id + + '}'; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java index 368714b2dd3..85a0d912e4c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/NotQueryable.java @@ -22,6 +22,9 @@ import java.lang.annotation.Target; /** + * Means: Don't allow this property to be used in queries. Used for auxiliary properties that have no + * representation in prism structures. + * * @author mederly */ @Target({ElementType.TYPE, ElementType.METHOD}) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ContainerIdGenerator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ContainerIdGenerator.java index a78029adfe4..29d7aaf5f96 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ContainerIdGenerator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/ContainerIdGenerator.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.util; import com.evolveum.midpoint.repo.sql.data.common.container.Container; +import com.evolveum.midpoint.repo.sql.data.common.container.L2Container; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.hibernate.HibernateException; @@ -34,12 +35,14 @@ public class ContainerIdGenerator implements IdentifierGenerator { @Override public Serializable generate(SessionImplementor session, Object object) throws HibernateException { - if (!(object instanceof Container)) { + if (object instanceof Container) { + return generate((Container) object); + } else if (object instanceof L2Container) { + return generate((L2Container) object); + } else { throw new HibernateException("Couldn't create id for '" + object.getClass().getSimpleName() + "' not instance of '" + Container.class.getName() + "'."); } - - return generate((Container) object); } private Integer generate(Container container) { @@ -64,4 +67,30 @@ private String toString(Container object) { return builder.toString(); } + + private Serializable generate(L2Container container) { + if (container.getId() != null && container.getId() != 0) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Created id='{}' for '{}'.", container.getId(), toString(container)); + } + return container.getId(); + } + + throw new RuntimeException("Unknown id, should not happen."); + } + + private String toString(L2Container container) { + StringBuilder builder = new StringBuilder(); + builder.append(container.getClass().getSimpleName()); + builder.append("["); + builder.append(container.getOwnerOwnerOid()); + builder.append(","); + builder.append(container.getOwnerId()); + builder.append(","); + builder.append(container.getId()); + builder.append("]"); + return builder.toString(); + } + + } From 74b8115c879ccc9cc763112d7adf40855062e7e5 Mon Sep 17 00:00:00 2001 From: Martin Lizner Date: Mon, 30 Nov 2015 20:38:54 +0100 Subject: [PATCH 040/116] Reports - Default AutoComplete removed for users, roles and organizations parameters due to performance issues. (MID-2739 moved to 3.4) --- config/initial-objects/090-report-audit.xml | 2 +- config/initial-objects/110-report-user-list.xml | 2 +- .../src/main/resources/initial-objects/090-report-audit.xml | 2 +- .../src/main/resources/initial-objects/110-report-user-list.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/initial-objects/090-report-audit.xml b/config/initial-objects/090-report-audit.xml index bcda6a4d344..de587fde930 100644 --- a/config/initial-objects/090-report-audit.xml +++ b/config/initial-objects/090-report-audit.xml @@ -24,7 +24,7 @@ Audit logs report Report made from audit records. true - + UEQ5NGJXd2dkbVZ5YzJsdmJqMGlNUzR3SWo4K0RRbzhJVVJQUTFSWlVFVWdhbUZ6Y0dWeVZHVnRjR3hoZEdVTkNpQWdVRlZDVEVsRElDSXRMeTlLWVhOd1pYSlNaWEJ2Y25Sekx5OUVWRVFnVkdWdGNHeGhkR1V2TDBWT0lnMEtJQ0FpYUhSMGNEb3ZMMnBoYzNCbGNuSmxjRzl5ZEhNdWMyOTFjbU5sWm05eVoyVXVibVYwTDJSMFpITXZhbUZ6Y0dWeWRHVnRjR3hoZEdVdVpIUmtJajROQ2p4cVlYTndaWEpVWlcxd2JHRjBaVDROQ2lBZ0lDQWdJQ0FnQ1R4emRIbHNaU0JtYjI1MFRtRnRaVDBpUkdWcVlWWjFJRk5oYm5NaUlHWnZiblJUYVhwbFBTSXhNQ0lnYUVGc2FXZHVQU0pNWldaMElpQnBjMFJsWm1GMWJIUTlJblJ5ZFdVaUlHbHpVR1JtUlcxaVpXUmtaV1E5SW5SeWRXVWlJQTBLQ1FrSkNTQWdJRzVoYldVOUlrSmhjMlVpSUhCa1prVnVZMjlrYVc1blBTSkpaR1Z1ZEdsMGVTMUlJaUJ3WkdaR2IyNTBUbUZ0WlQwaVJHVnFZVloxVTJGdWN5NTBkR1lpSUhaQmJHbG5iajBpVFdsa1pHeGxJajROQ2drSkNUd3ZjM1I1YkdVK0RRb0pDUWs4YzNSNWJHVWdZbUZqYTJOdmJHOXlQU0lqTWpZM09UazBJaUJtYjI1MFUybDZaVDBpTWpZaUlHWnZjbVZqYjJ4dmNqMGlJMFpHUmtaR1JpSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWxScGRHeGxJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBpQU5DZ2tKQ1R4emRIbHNaU0JtYjI1MFUybDZaVDBpTVRJaUlHWnZjbVZqYjJ4dmNqMGlJekF3TURBd01DSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSWdibUZ0WlQwaVVHRm5aU0JvWldGa1pYSWlEUW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYzNSNWJHVTlJa0poYzJVaUx6NE5DZ2tKQ1R4emRIbHNaU0JpWVdOclkyOXNiM0k5SWlNek16TXpNek1pSUdadmJuUlRhWHBsUFNJeE1pSWdabTl5WldOdmJHOXlQU0lqUmtaR1JrWkdJaUJvUVd4cFoyNDlJa05sYm5SbGNpSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYzBSbFptRjFiSFE5SW1aaGJITmxJaUJ0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWtOdmJIVnRiaUJvWldGa1pYSWlJSE4wZVd4bFBTSkNZWE5sSWk4K0RRb0pDUWs4YzNSNWJHVWdhWE5DYjJ4a1BTSm1ZV3h6WlNJZ2FYTkVaV1poZFd4MFBTSm1ZV3h6WlNJZ2JtRnRaVDBpUkdWMFlXbHNJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBnMEtJQ0FnSUNBZ0lDQWdJQ0FnUEhOMGVXeGxJR2x6UW05c1pEMGlabUZzYzJVaUlHbHpSR1ZtWVhWc2REMGlabUZzYzJVaUlHNWhiV1U5SWtOdlpHVWlJSE4wZVd4bFBTSkNZWE5sSWlCbWIyNTBVMmw2WlQwaU9TSXZQZzBLQ1FrSlBITjBlV3hsSUdadmJuUlRhWHBsUFNJNUlpQm1iM0psWTI5c2IzSTlJaU13TURBd01EQWlJR2x6UkdWbVlYVnNkRDBpWm1Gc2MyVWlJRzVoYldVOUlsQmhaMlVnWm05dmRHVnlJZzBLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhOMGVXeGxQU0pDWVhObElpOCtEUW9KQ1R3dmFtRnpjR1Z5VkdWdGNHeGhkR1Ur html JRSwapFileVirtualizer diff --git a/config/initial-objects/110-report-user-list.xml b/config/initial-objects/110-report-user-list.xml index 7b7ff974152..2922f086513 100644 --- a/config/initial-objects/110-report-user-list.xml +++ b/config/initial-objects/110-report-user-list.xml @@ -20,7 +20,7 @@ http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user true - + UEQ5NGJXd2dkbVZ5YzJsdmJqMGlNUzR3SWo4K0RRbzhJVVJQUTFSWlVFVWdhbUZ6Y0dWeVZHVnRjR3hoZEdVTkNpQWdVRlZDVEVsRElDSXRMeTlLWVhOd1pYSlNaWEJ2Y25Sekx5OUVWRVFnVkdWdGNHeGhkR1V2TDBWT0lnMEtJQ0FpYUhSMGNEb3ZMMnBoYzNCbGNuSmxjRzl5ZEhNdWMyOTFjbU5sWm05eVoyVXVibVYwTDJSMFpITXZhbUZ6Y0dWeWRHVnRjR3hoZEdVdVpIUmtJajROQ2p4cVlYTndaWEpVWlcxd2JHRjBaVDROQ2lBZ0lDQWdJQ0FnQ1R4emRIbHNaU0JtYjI1MFRtRnRaVDBpUkdWcVlWWjFJRk5oYm5NaUlHWnZiblJUYVhwbFBTSXhNQ0lnYUVGc2FXZHVQU0pNWldaMElpQnBjMFJsWm1GMWJIUTlJblJ5ZFdVaUlHbHpVR1JtUlcxaVpXUmtaV1E5SW5SeWRXVWlJQTBLQ1FrSkNTQWdJRzVoYldVOUlrSmhjMlVpSUhCa1prVnVZMjlrYVc1blBTSkpaR1Z1ZEdsMGVTMUlJaUJ3WkdaR2IyNTBUbUZ0WlQwaVJHVnFZVloxVTJGdWN5NTBkR1lpSUhaQmJHbG5iajBpVFdsa1pHeGxJajROQ2drSkNUd3ZjM1I1YkdVK0RRb0pDUWs4YzNSNWJHVWdZbUZqYTJOdmJHOXlQU0lqTWpZM09UazBJaUJtYjI1MFUybDZaVDBpTWpZaUlHWnZjbVZqYjJ4dmNqMGlJMFpHUmtaR1JpSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWxScGRHeGxJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBpQU5DZ2tKQ1R4emRIbHNaU0JtYjI1MFUybDZaVDBpTVRJaUlHWnZjbVZqYjJ4dmNqMGlJekF3TURBd01DSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSWdibUZ0WlQwaVVHRm5aU0JvWldGa1pYSWlEUW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYzNSNWJHVTlJa0poYzJVaUx6NE5DZ2tKQ1R4emRIbHNaU0JpWVdOclkyOXNiM0k5SWlNek16TXpNek1pSUdadmJuUlRhWHBsUFNJeE1pSWdabTl5WldOdmJHOXlQU0lqUmtaR1JrWkdJaUJvUVd4cFoyNDlJa05sYm5SbGNpSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYzBSbFptRjFiSFE5SW1aaGJITmxJaUJ0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWtOdmJIVnRiaUJvWldGa1pYSWlJSE4wZVd4bFBTSkNZWE5sSWk4K0RRb0pDUWs4YzNSNWJHVWdhWE5DYjJ4a1BTSm1ZV3h6WlNJZ2FYTkVaV1poZFd4MFBTSm1ZV3h6WlNJZ2JtRnRaVDBpUkdWMFlXbHNJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBnMEtJQ0FnSUNBZ0lDQWdJQ0FnUEhOMGVXeGxJR2x6UW05c1pEMGlabUZzYzJVaUlHbHpSR1ZtWVhWc2REMGlabUZzYzJVaUlHNWhiV1U5SWtOdlpHVWlJSE4wZVd4bFBTSkNZWE5sSWlCbWIyNTBVMmw2WlQwaU9TSXZQZzBLQ1FrSlBITjBlV3hsSUdadmJuUlRhWHBsUFNJNUlpQm1iM0psWTI5c2IzSTlJaU13TURBd01EQWlJR2x6UkdWbVlYVnNkRDBpWm1Gc2MyVWlJRzVoYldVOUlsQmhaMlVnWm05dmRHVnlJZzBLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhOMGVXeGxQU0pDWVhObElpOCtEUW9KQ1R3dmFtRnpjR1Z5VkdWdGNHeGhkR1Ur pdf JRSwapFileVirtualizer diff --git a/gui/admin-gui/src/main/resources/initial-objects/090-report-audit.xml b/gui/admin-gui/src/main/resources/initial-objects/090-report-audit.xml index bcda6a4d344..de587fde930 100644 --- a/gui/admin-gui/src/main/resources/initial-objects/090-report-audit.xml +++ b/gui/admin-gui/src/main/resources/initial-objects/090-report-audit.xml @@ -24,7 +24,7 @@ Audit logs report Report made from audit records. true - + UEQ5NGJXd2dkbVZ5YzJsdmJqMGlNUzR3SWo4K0RRbzhJVVJQUTFSWlVFVWdhbUZ6Y0dWeVZHVnRjR3hoZEdVTkNpQWdVRlZDVEVsRElDSXRMeTlLWVhOd1pYSlNaWEJ2Y25Sekx5OUVWRVFnVkdWdGNHeGhkR1V2TDBWT0lnMEtJQ0FpYUhSMGNEb3ZMMnBoYzNCbGNuSmxjRzl5ZEhNdWMyOTFjbU5sWm05eVoyVXVibVYwTDJSMFpITXZhbUZ6Y0dWeWRHVnRjR3hoZEdVdVpIUmtJajROQ2p4cVlYTndaWEpVWlcxd2JHRjBaVDROQ2lBZ0lDQWdJQ0FnQ1R4emRIbHNaU0JtYjI1MFRtRnRaVDBpUkdWcVlWWjFJRk5oYm5NaUlHWnZiblJUYVhwbFBTSXhNQ0lnYUVGc2FXZHVQU0pNWldaMElpQnBjMFJsWm1GMWJIUTlJblJ5ZFdVaUlHbHpVR1JtUlcxaVpXUmtaV1E5SW5SeWRXVWlJQTBLQ1FrSkNTQWdJRzVoYldVOUlrSmhjMlVpSUhCa1prVnVZMjlrYVc1blBTSkpaR1Z1ZEdsMGVTMUlJaUJ3WkdaR2IyNTBUbUZ0WlQwaVJHVnFZVloxVTJGdWN5NTBkR1lpSUhaQmJHbG5iajBpVFdsa1pHeGxJajROQ2drSkNUd3ZjM1I1YkdVK0RRb0pDUWs4YzNSNWJHVWdZbUZqYTJOdmJHOXlQU0lqTWpZM09UazBJaUJtYjI1MFUybDZaVDBpTWpZaUlHWnZjbVZqYjJ4dmNqMGlJMFpHUmtaR1JpSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWxScGRHeGxJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBpQU5DZ2tKQ1R4emRIbHNaU0JtYjI1MFUybDZaVDBpTVRJaUlHWnZjbVZqYjJ4dmNqMGlJekF3TURBd01DSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSWdibUZ0WlQwaVVHRm5aU0JvWldGa1pYSWlEUW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYzNSNWJHVTlJa0poYzJVaUx6NE5DZ2tKQ1R4emRIbHNaU0JpWVdOclkyOXNiM0k5SWlNek16TXpNek1pSUdadmJuUlRhWHBsUFNJeE1pSWdabTl5WldOdmJHOXlQU0lqUmtaR1JrWkdJaUJvUVd4cFoyNDlJa05sYm5SbGNpSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYzBSbFptRjFiSFE5SW1aaGJITmxJaUJ0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWtOdmJIVnRiaUJvWldGa1pYSWlJSE4wZVd4bFBTSkNZWE5sSWk4K0RRb0pDUWs4YzNSNWJHVWdhWE5DYjJ4a1BTSm1ZV3h6WlNJZ2FYTkVaV1poZFd4MFBTSm1ZV3h6WlNJZ2JtRnRaVDBpUkdWMFlXbHNJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBnMEtJQ0FnSUNBZ0lDQWdJQ0FnUEhOMGVXeGxJR2x6UW05c1pEMGlabUZzYzJVaUlHbHpSR1ZtWVhWc2REMGlabUZzYzJVaUlHNWhiV1U5SWtOdlpHVWlJSE4wZVd4bFBTSkNZWE5sSWlCbWIyNTBVMmw2WlQwaU9TSXZQZzBLQ1FrSlBITjBlV3hsSUdadmJuUlRhWHBsUFNJNUlpQm1iM0psWTI5c2IzSTlJaU13TURBd01EQWlJR2x6UkdWbVlYVnNkRDBpWm1Gc2MyVWlJRzVoYldVOUlsQmhaMlVnWm05dmRHVnlJZzBLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhOMGVXeGxQU0pDWVhObElpOCtEUW9KQ1R3dmFtRnpjR1Z5VkdWdGNHeGhkR1Ur html JRSwapFileVirtualizer diff --git a/gui/admin-gui/src/main/resources/initial-objects/110-report-user-list.xml b/gui/admin-gui/src/main/resources/initial-objects/110-report-user-list.xml index 7b7ff974152..2922f086513 100644 --- a/gui/admin-gui/src/main/resources/initial-objects/110-report-user-list.xml +++ b/gui/admin-gui/src/main/resources/initial-objects/110-report-user-list.xml @@ -20,7 +20,7 @@ http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user true - + UEQ5NGJXd2dkbVZ5YzJsdmJqMGlNUzR3SWo4K0RRbzhJVVJQUTFSWlVFVWdhbUZ6Y0dWeVZHVnRjR3hoZEdVTkNpQWdVRlZDVEVsRElDSXRMeTlLWVhOd1pYSlNaWEJ2Y25Sekx5OUVWRVFnVkdWdGNHeGhkR1V2TDBWT0lnMEtJQ0FpYUhSMGNEb3ZMMnBoYzNCbGNuSmxjRzl5ZEhNdWMyOTFjbU5sWm05eVoyVXVibVYwTDJSMFpITXZhbUZ6Y0dWeWRHVnRjR3hoZEdVdVpIUmtJajROQ2p4cVlYTndaWEpVWlcxd2JHRjBaVDROQ2lBZ0lDQWdJQ0FnQ1R4emRIbHNaU0JtYjI1MFRtRnRaVDBpUkdWcVlWWjFJRk5oYm5NaUlHWnZiblJUYVhwbFBTSXhNQ0lnYUVGc2FXZHVQU0pNWldaMElpQnBjMFJsWm1GMWJIUTlJblJ5ZFdVaUlHbHpVR1JtUlcxaVpXUmtaV1E5SW5SeWRXVWlJQTBLQ1FrSkNTQWdJRzVoYldVOUlrSmhjMlVpSUhCa1prVnVZMjlrYVc1blBTSkpaR1Z1ZEdsMGVTMUlJaUJ3WkdaR2IyNTBUbUZ0WlQwaVJHVnFZVloxVTJGdWN5NTBkR1lpSUhaQmJHbG5iajBpVFdsa1pHeGxJajROQ2drSkNUd3ZjM1I1YkdVK0RRb0pDUWs4YzNSNWJHVWdZbUZqYTJOdmJHOXlQU0lqTWpZM09UazBJaUJtYjI1MFUybDZaVDBpTWpZaUlHWnZjbVZqYjJ4dmNqMGlJMFpHUmtaR1JpSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWxScGRHeGxJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBpQU5DZ2tKQ1R4emRIbHNaU0JtYjI1MFUybDZaVDBpTVRJaUlHWnZjbVZqYjJ4dmNqMGlJekF3TURBd01DSWdhWE5FWldaaGRXeDBQU0ptWVd4elpTSWdibUZ0WlQwaVVHRm5aU0JvWldGa1pYSWlEUW9nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYzNSNWJHVTlJa0poYzJVaUx6NE5DZ2tKQ1R4emRIbHNaU0JpWVdOclkyOXNiM0k5SWlNek16TXpNek1pSUdadmJuUlRhWHBsUFNJeE1pSWdabTl5WldOdmJHOXlQU0lqUmtaR1JrWkdJaUJvUVd4cFoyNDlJa05sYm5SbGNpSU5DaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYzBSbFptRjFiSFE5SW1aaGJITmxJaUJ0YjJSbFBTSlBjR0Z4ZFdVaUlHNWhiV1U5SWtOdmJIVnRiaUJvWldGa1pYSWlJSE4wZVd4bFBTSkNZWE5sSWk4K0RRb0pDUWs4YzNSNWJHVWdhWE5DYjJ4a1BTSm1ZV3h6WlNJZ2FYTkVaV1poZFd4MFBTSm1ZV3h6WlNJZ2JtRnRaVDBpUkdWMFlXbHNJaUJ6ZEhsc1pUMGlRbUZ6WlNJdlBnMEtJQ0FnSUNBZ0lDQWdJQ0FnUEhOMGVXeGxJR2x6UW05c1pEMGlabUZzYzJVaUlHbHpSR1ZtWVhWc2REMGlabUZzYzJVaUlHNWhiV1U5SWtOdlpHVWlJSE4wZVd4bFBTSkNZWE5sSWlCbWIyNTBVMmw2WlQwaU9TSXZQZzBLQ1FrSlBITjBlV3hsSUdadmJuUlRhWHBsUFNJNUlpQm1iM0psWTI5c2IzSTlJaU13TURBd01EQWlJR2x6UkdWbVlYVnNkRDBpWm1Gc2MyVWlJRzVoYldVOUlsQmhaMlVnWm05dmRHVnlJZzBLSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhOMGVXeGxQU0pDWVhObElpOCtEUW9KQ1R3dmFtRnpjR1Z5VkdWdGNHeGhkR1Ur pdf JRSwapFileVirtualizer From b23be2b6492cfba9b0d16d95797f86a8e8823287 Mon Sep 17 00:00:00 2001 From: Viliam Repan Date: Mon, 30 Nov 2015 21:41:55 +0100 Subject: [PATCH 041/116] MID-2730 repository datasource loading pool closing fix --- .../src/main/resources/ctx-repository-session.xml | 2 +- .../midpoint/repo/sql/DataSourceFactory.java | 12 +++++++++++- .../src/main/resources/ctx-repository-session.xml | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml b/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml index 149aed48e33..d029cc13b3b 100644 --- a/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml +++ b/repo/repo-sql-impl-test/src/main/resources/ctx-repository-session.xml @@ -21,7 +21,7 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true" default-autowire="byName"> - + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/DataSourceFactory.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/DataSourceFactory.java index d8b17cdaa5a..970fc25d4bb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/DataSourceFactory.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/DataSourceFactory.java @@ -38,6 +38,8 @@ public class DataSourceFactory { private SqlRepositoryConfiguration configuration; + private DataSource dataSource; + public void setConfiguration(SqlRepositoryConfiguration configuration) { this.configuration = configuration; } @@ -56,7 +58,8 @@ public DataSource createDataSource() throws RepositoryServiceFactoryException { } LOGGER.info("Constructing default C3P0 datasource with connection pooling."); - return createC3P0DataSource(); + dataSource = createC3P0DataSource(); + return dataSource; } catch (Exception ex) { throw new RepositoryServiceFactoryException("Couldn't initialize datasource, reason: " + ex.getMessage(), ex); } @@ -86,4 +89,11 @@ private DataSource createC3P0DataSource() throws PropertyVetoException { return ds; } + + public void destroy() { + if (dataSource instanceof ComboPooledDataSource) { + ComboPooledDataSource ds = (ComboPooledDataSource) dataSource; + ds.close(); + } + } } diff --git a/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml b/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml index 6bdaaa23a90..f0f3d9f5802 100644 --- a/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml +++ b/repo/repo-sql-impl/src/main/resources/ctx-repository-session.xml @@ -21,7 +21,7 @@ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true" default-autowire="byName"> - + From 06a9ff1055e2df087000d1dd8b2616689f139564 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 1 Dec 2015 09:36:41 +0100 Subject: [PATCH 042/116] Preliminary support for RDecision, passing the tests. --- .../common/RAccessCertificationCampaign.java | 2 +- .../container/RAccessCertificationCase.java | 14 ++++---- .../RAccessCertificationDecision.java | 23 +++++++----- .../common/container/RContainerReference.java | 2 +- .../sql/data/common/id/RL2ContainerId.java | 3 ++ .../sql/helpers/CertificationCaseHelper.java | 11 ++++-- .../repo/sql/util/EntityStateInterceptor.java | 3 +- .../sql/util/PrismIdentifierGenerator.java | 36 ++++++++++++++++--- 8 files changed, 70 insertions(+), 24 deletions(-) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 49875deb471..12ef921ec9e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -127,7 +127,7 @@ public static void copyFromJAXB(AccessCertificationCampaignType jaxb, RAccessCer if (!cases.isEmpty()) { for (AccessCertificationCaseType case1 : cases) { case1.setCampaignRef(ObjectTypeUtil.createObjectRef(jaxb)); - RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(repo, case1, prismContext); + RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(repo, case1, generatorResult, prismContext); rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); repo.getCases().add(rCase); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 76436561a55..f98f8f4a88d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -28,6 +28,7 @@ import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query.definition.OwnerGetter; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; +import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; @@ -314,20 +315,21 @@ public void setTransient(Boolean trans) { this.trans = trans; } - public static RAccessCertificationCase toRepo(RAccessCertificationCampaign owner, AccessCertificationCaseType case1, PrismContext prismContext) { - RAccessCertificationCase rCase = toRepo(case1, prismContext); + public static RAccessCertificationCase toRepo(RAccessCertificationCampaign owner, AccessCertificationCaseType case1, IdGeneratorResult generatorResult, PrismContext prismContext) { + RAccessCertificationCase rCase = toRepo(case1, generatorResult, prismContext); rCase.setOwner(owner); return rCase; } - public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificationCaseType case1, PrismContext prismContext) { - RAccessCertificationCase rCase = toRepo(case1, prismContext); + public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificationCaseType case1, IdGeneratorResult generatorResult, PrismContext prismContext) { + RAccessCertificationCase rCase = toRepo(case1, generatorResult, prismContext); rCase.setOwnerOid(ownerOid); return rCase; } - private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, PrismContext prismContext) { + private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, IdGeneratorResult generatorResult, PrismContext prismContext) { RAccessCertificationCase rCase = new RAccessCertificationCase(); + rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); rCase.setId(RUtil.toInteger(case1.getId())); rCase.setObjectRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getObjectRef(), prismContext)); rCase.setTargetRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getTargetRef(), prismContext)); @@ -340,7 +342,7 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 rCase.setCurrentResponse(RUtil.getRepoEnumValue(case1.getCurrentResponse(), RAccessCertificationResponse.class)); rCase.setCurrentResponseStage(case1.getCurrentResponseStage()); for (AccessCertificationDecisionType decision : case1.getDecision()) { - RAccessCertificationDecision rDecision = RAccessCertificationDecision.toRepo(rCase, decision, prismContext); + RAccessCertificationDecision rDecision = RAccessCertificationDecision.toRepo(rCase, decision, generatorResult, prismContext); rCase.getDecisions().add(rDecision); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java index 2736dd44e9a..fffa66f76bb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.repo.sql.data.common.id.RL2ContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; +import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -89,6 +90,9 @@ public String getOwnerOwnerOid() { @NotQueryable @Column(name = "owner_id") public Integer getOwnerId() { + if (owner != null && ownerId == null) { + ownerId = owner.getId(); + } return ownerId; } @@ -167,21 +171,22 @@ public void setTransient(Boolean trans) { this.trans = trans; } - public static RAccessCertificationDecision toRepo(RAccessCertificationCase owningCase, AccessCertificationDecisionType decision, PrismContext prismContext) { - RAccessCertificationDecision rDecision = toRepo(decision, prismContext); + public static RAccessCertificationDecision toRepo(RAccessCertificationCase owningCase, AccessCertificationDecisionType decision, IdGeneratorResult generatorResult, PrismContext prismContext) { + RAccessCertificationDecision rDecision = toRepo(decision, generatorResult, prismContext); rDecision.setOwner(owningCase); return rDecision; } - public static RAccessCertificationDecision toRepo(String campaignOid, int caseId, AccessCertificationDecisionType decision, PrismContext prismContext) { - RAccessCertificationDecision rCase = toRepo(decision, prismContext); - rCase.setOwnerOwnerOid(campaignOid); - rCase.setOwnerId(caseId); - return rCase; - } +// public static RAccessCertificationDecision toRepo(String campaignOid, int caseId, AccessCertificationDecisionType decision, PrismContext prismContext) { +// RAccessCertificationDecision rCase = toRepo(decision, prismContext); +// rCase.setOwnerOwnerOid(campaignOid); +// rCase.setOwnerId(caseId); +// return rCase; +// } - private static RAccessCertificationDecision toRepo(AccessCertificationDecisionType decision, PrismContext prismContext) { + private static RAccessCertificationDecision toRepo(AccessCertificationDecisionType decision, IdGeneratorResult generatorResult, PrismContext prismContext) { RAccessCertificationDecision rDecision = new RAccessCertificationDecision(); + rDecision.setTransient(generatorResult.isTransient(decision.asPrismContainerValue())); rDecision.setId(RUtil.toInteger(decision.getId())); rDecision.setStageNumber(decision.getStageNumber()); rDecision.setReviewerRef(RUtil.jaxbRefToEmbeddedRepoRef(decision.getReviewerRef(), prismContext)); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java index 76f42684252..cfcef4daea8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RContainerReference.java @@ -60,7 +60,7 @@ public RContainerReference() { } @NotQueryable - protected abstract Container getOwner(); + public abstract Container getOwner(); @NotQueryable protected String getOwnerOid() { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java index 95a56b19590..d097d631ec9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/id/RL2ContainerId.java @@ -29,6 +29,9 @@ public class RL2ContainerId implements Serializable { private Integer ownerId; private Integer id; + public RL2ContainerId() { + } + public RL2ContainerId(String ownerOwnerOid, Integer ownerId, Integer id) { this.ownerOwnerOid = ownerOwnerOid; this.ownerId = ownerId; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 7d01a2e58ed..e711ba92e43 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -27,6 +27,8 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; +import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; +import com.evolveum.midpoint.repo.sql.util.PrismIdentifierGenerator; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; @@ -95,7 +97,7 @@ public void addCertificationCampaignCases(Session session, String campaignOid, C AccessCertificationCaseType caseType = new AccessCertificationCaseType(); caseType.setupContainerValue(value); caseType.setCampaignRef(ObjectTypeUtil.createObjectRef(campaignOid, ObjectTypes.ACCESS_CERTIFICATION_CAMPAIGN)); - RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, prismContext); + RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, new IdGeneratorResult(), prismContext); row.setId(currentId); currentId++; session.save(row); @@ -213,7 +215,12 @@ private void updateCasesContent(Session session, String campaignOid, Collection< delta.setParentPath(delta.getParentPath().tail(2)); // remove "case[id]" from the delta path delta.applyTo(aCase.asPrismContainerValue()); - RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(campaignOid, aCase, prismContext); + + // TODO fix this temporary hack: doesn't work quite as expected (new decisions are marked as non-transient) + PrismIdentifierGenerator generator = new PrismIdentifierGenerator(); + IdGeneratorResult generatorResult = generator.generate(aCase, PrismIdentifierGenerator.Operation.MODIFY); + + RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(campaignOid, aCase, generatorResult, prismContext); session.merge(rCase); LOGGER.trace("Access certification case " + rCase + " merged."); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/EntityStateInterceptor.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/EntityStateInterceptor.java index edcd6d58b39..64c4fa9e4f5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/EntityStateInterceptor.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/EntityStateInterceptor.java @@ -6,6 +6,7 @@ import com.evolveum.midpoint.repo.sql.data.common.any.RAssignmentExtension; import com.evolveum.midpoint.repo.sql.data.common.any.ROExtValue; import com.evolveum.midpoint.repo.sql.data.common.container.RAssignmentReference; +import com.evolveum.midpoint.repo.sql.data.common.container.RContainerReference; import org.hibernate.EmptyInterceptor; /** @@ -23,7 +24,7 @@ public Boolean isTransient(Object entity) { RObjectReference ref = (RObjectReference) entity; return isTransient(ref.getOwner()); } else if (entity instanceof RAssignmentReference) { - RAssignmentReference ref = (RAssignmentReference) entity; + RContainerReference ref = (RContainerReference) entity; return isTransient(ref.getOwner()); } else if (entity instanceof RAssignmentExtension) { RAssignmentExtension ext = (RAssignmentExtension) entity; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/PrismIdentifierGenerator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/PrismIdentifierGenerator.java index 696d336d650..6cb4c4dadba 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/PrismIdentifierGenerator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/util/PrismIdentifierGenerator.java @@ -1,9 +1,12 @@ package com.evolveum.midpoint.repo.sql.util; +import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; @@ -48,14 +51,16 @@ private void generateIdForObject(PrismObject object, IdGeneratorResult result, O if (object == null) { return; } - List containers = getChildrenContainers(object); + generateIdsForContainers(containers, result, operation); + } + + private void generateIdsForContainers(List containers, IdGeneratorResult result, Operation operation) { Set usedIds = new HashSet<>(); for (PrismContainer c : containers) { if (c == null || c.getValues() == null) { continue; } - for (PrismContainerValue val : (List) c.getValues()) { if (val.getId() != null) { usedIds.add(val.getId()); @@ -102,6 +107,18 @@ private List getChildrenContainers(PrismObject parent) { containers.add(parent.findContainer(LookupTableType.F_ROW)); } + if (AccessCertificationCampaignType.class.isAssignableFrom(parent.getCompileTimeClass())) { + PrismContainer caseContainer = parent.findContainer(AccessCertificationCampaignType.F_CASE); + containers.add(caseContainer); + if (caseContainer != null) { + List casePcvList = caseContainer.getValues(); + for (PrismContainerValue casePcv : casePcvList) { + PrismContainer decisionContainer = casePcv.findContainer(AccessCertificationCaseType.F_DECISION); + containers.add(decisionContainer); + } + } + } + if (FocusType.class.isAssignableFrom(parent.getCompileTimeClass())) { containers.add(parent.findContainer(FocusType.F_ASSIGNMENT)); } @@ -115,10 +132,21 @@ private List getChildrenContainers(PrismObject parent) { containers.add(policyConstraints.findContainer(PolicyConstraintsType.F_MAX_ASSIGNEES)); containers.add(policyConstraints.findContainer(PolicyConstraintsType.F_MIN_ASSIGNEES)); } - - } return containers; } + + public IdGeneratorResult generate(Containerable containerable, Operation operation) { + IdGeneratorResult result = new IdGeneratorResult(); + if (!(containerable instanceof AccessCertificationCaseType)) { + return result; + } + AccessCertificationCaseType aCase = (AccessCertificationCaseType) containerable; + PrismContainer decisionContainer = aCase.asPrismContainerValue().findContainer(AccessCertificationCaseType.F_DECISION); + if (decisionContainer != null) { + generateIdsForContainers(Arrays.asList(decisionContainer), result, operation); + } + return result; + } } From 6bd0cc54a822621e847d1c01c2047e76edb71bc0 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 1 Dec 2015 09:37:12 +0100 Subject: [PATCH 043/116] Virtual zero-path entities for metadata and construction, cleaning up query interpreter further. --- .../repo/sql/data/common/RObject.java | 18 +++++- .../data/common/container/RAssignment.java | 22 ++++++++ .../sql/query/definition/VirtualEntity.java | 5 +- .../sql/query2/QueryDefinitionRegistry2.java | 12 ++-- .../definition/ClassDefinitionParser.java | 20 ++++++- .../definition/JpaDataNodeDefinition.java | 4 +- .../definition/JpaEntityDefinition.java | 55 +++---------------- .../JpaEntityPointerDefinition.java | 14 ++++- 8 files changed, 90 insertions(+), 60 deletions(-) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index a5fd56b44c8..560f766d24a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -35,6 +35,8 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner; import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; @@ -45,6 +47,7 @@ import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; import org.apache.commons.lang.StringUtils; @@ -109,8 +112,19 @@ @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), @NamedQuery(name = "get.campaignCase", query = "select c.fullObject from RAccessCertificationCase c where c.ownerOid=:ownerOid and c.id=:id") }) -@QueryEntity(anyElements = { - @VirtualAny(jaxbNameLocalPart = "extension", ownerType = RObjectExtensionType.EXTENSION)}) +@QueryEntity( + anyElements = { + @VirtualAny(jaxbNameLocalPart = "extension", ownerType = RObjectExtensionType.EXTENSION) + }, + entities = { + @VirtualEntity( + jaxbName = @JaxbName(localPart = "metadata"), + jaxbType = MetadataType.class, + jpaName = "", + jpaType = Serializable.class // dummy value (ignored) + ) + } + ) @Entity @Table(name = "m_object", indexes = { @Index(name = "iObjectNameOrig", columnList = "name_orig"), diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java index 580c79f847c..f67755fa38b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java @@ -26,7 +26,10 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RAssignmentOwner; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; @@ -34,6 +37,8 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; import org.hibernate.annotations.Cascade; @@ -42,6 +47,7 @@ import javax.persistence.*; import javax.xml.datatype.XMLGregorianCalendar; +import java.io.Serializable; import java.util.HashSet; import java.util.Set; @@ -50,6 +56,22 @@ */ @JaxbType(type = AssignmentType.class) @Entity +@QueryEntity( + entities = { + @VirtualEntity( + jaxbName = @JaxbName(localPart = "metadata"), + jaxbType = MetadataType.class, + jpaName = "", + jpaType = Serializable.class // dummy value (ignored) + ), + @VirtualEntity( + jaxbName = @JaxbName(localPart = "construction"), + jaxbType = ConstructionType.class, + jpaName = "", + jpaType = Serializable.class // dummy value (ignored) + ) + } +) @IdClass(RContainerId.class) @Table(name = "m_assignment", indexes = { @Index(name = "iAssignmentAdministrative", columnList = "administrativeStatus"), diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualEntity.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualEntity.java index d8ec82fcd0d..64395696023 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualEntity.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/VirtualEntity.java @@ -25,7 +25,7 @@ /** * @author lazyman */ -@Target({ElementType.METHOD}) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface VirtualEntity { @@ -37,5 +37,6 @@ Class jpaType(); - VirtualQueryParam[] additionalParams() default {}; + // VirtualQueryParam[] additionalParams() default {}; + // not supported for now } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java index a614acc8e1c..9e8889b7b49 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryDefinitionRegistry2.java @@ -101,12 +101,14 @@ public void visit(Visitable visitable) { entityDef.setSuperclassDefinition(superclassDefinition); } else if (visitable instanceof JpaEntityPointerDefinition) { JpaEntityPointerDefinition entPtrDef = ((JpaEntityPointerDefinition) visitable); - Class referencedEntityJpaClass = entPtrDef.getJpaClass(); - JpaEntityDefinition realEntDef = definitionsByClass.get(referencedEntityJpaClass); - if (realEntDef == null) { - throw new IllegalStateException("Couldn't find entity definition for " + referencedEntityJpaClass); + if (!entPtrDef.isResolved()) { + Class referencedEntityJpaClass = entPtrDef.getJpaClass(); + JpaEntityDefinition realEntDef = definitionsByClass.get(referencedEntityJpaClass); + if (realEntDef == null) { + throw new IllegalStateException("Couldn't find entity definition for " + referencedEntityJpaClass); + } + entPtrDef.setResolvedEntityDefinition(realEntDef); } - entPtrDef.setResolvedEntityDefinition(realEntDef); } } }; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 452ba6c07c8..b03f74355cf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -28,6 +28,7 @@ import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; +import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; import com.evolveum.midpoint.repo.sql.util.ClassMapper; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.constants.ObjectTypes; @@ -202,13 +203,30 @@ private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityDefinition e entityDef.addDefinition(linkDefinition); } - // TODO virtual entity collections (for metadata and construction) + for (VirtualEntity entity : qEntity.entities()) { + QName jaxbName = createQName(entity.jaxbName()); + String jpaName = normalizeJpaName(entity.jpaName()); + if (jpaName != null) { + throw new IllegalStateException("Only self-pointing virtual entities are supported for now; this one is not: " + jaxbName + " in " + entityDef); + } + JpaDataNodeDefinition target = new JpaEntityPointerDefinition(entityDef); // pointer to avoid loops + JpaLinkDefinition linkDefinition = new JpaLinkDefinition(jaxbName, jpaName, null, false, target); + entityDef.addDefinition(linkDefinition); + } } private QName createQName(JaxbName name) { return new QName(name.namespace(), name.localPart()); } + private String normalizeJpaName(String name) { + if (StringUtils.isEmpty(name)) { + return null; // "" -> null + } else { + return name; + } + } + private boolean isEntity(Class type) { if (RPolyString.class.isAssignableFrom(type)) { //it's hibernate entity but from prism point of view it's property diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java index ce176671720..8e8020cc8ad 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java @@ -86,13 +86,11 @@ public Class getJaxbClass() { /** * Tries to find "next step" in the translation process for a given ItemPath. - * Parts of the path that have no representation in the repository (e.g. metadata, - * construction) are skipped. * * @param path A path to be resolved. Always non-null and non-empty. Should produce at least one transition. * @return * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain - * and the unresolved remainder of the path. + * and the unresolved remainder of the path. The transition may be empty ("self") e.g. for metadata or construction. * - If the search was not successful, returns null. * * Method is not supported on AnyDefinition! diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java index 7c16bc5750e..a0e1701d28f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java @@ -60,7 +60,7 @@ public JpaEntityDefinition(Class jpaClass, Class jaxbClass) { } public void addDefinition(JpaLinkDefinition definition) { - JpaLinkDefinition oldDef = findLinkDefinition(definition.getItemPathSegment(), JpaDataNodeDefinition.class); + JpaLinkDefinition oldDef = findRawLinkDefinition(definition.getItemPathSegment(), JpaDataNodeDefinition.class); if (oldDef != null) { definitions.remove(oldDef); } @@ -71,7 +71,7 @@ public void sortDefinitions() { Collections.sort(definitions, new LinkDefinitionComparator()); } - private JpaLinkDefinition findLinkDefinition(ItemPathSegment itemPathSegment, Class type) { + private JpaLinkDefinition findRawLinkDefinition(ItemPathSegment itemPathSegment, Class type) { Validate.notNull(itemPathSegment, "ItemPathSegment must not be null."); Validate.notNull(type, "Definition type must not be null."); @@ -167,61 +167,24 @@ public JpaEntityDefinition getSuperclassDefinition() { @Override public DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException { - // first treat known discrepancies between prism structure and repo representation: - // metadata -> none, - // construction/resourceRef -> resourceRef - // - // TODO replace with the use of VirtualEntity with null jpaName - while (skipFirstItem(path)) { - path = path.tail(); - } - if (ItemPath.isNullOrEmpty(path)) { // doesn't fulfill precondition return null; } - JpaLinkDefinition link = findLinkDefinition(path.first(), JpaDataNodeDefinition.class); - if (link == null) { - return null; - } else { - link.resolveEntityPointer(); - return new DataSearchResult(link, path.tail()); - } - } - - - private boolean skipFirstItem(ItemPath path) throws QueryException { - if (ItemPath.isNullOrEmpty(path)) { - return false; - } ItemPathSegment first = path.first(); if (first instanceof IdItemPathSegment) { - throw new QueryException("ID path segments are not allowed in query: " + path); + throw new QueryException("ID item path segments are not allowed in query: " + path); } else if (first instanceof ObjectReferencePathSegment) { throw new QueryException("'@' path segment cannot be used in the context of an entity " + this); - } else if (first instanceof ParentPathSegment) { - return false; } - QName firstName = ((NameItemPathSegment) first).getName(); - - // metadata -> null - if (QNameUtil.match(firstName, ObjectType.F_METADATA)) { - return true; - } - - // construction/resourceRef -> construction - ItemPath remainder = path.tail(); - if (remainder.isEmpty() || !(remainder.first() instanceof NameItemPathSegment)) { - return false; - } - NameItemPathSegment second = ((NameItemPathSegment) (remainder.first())); - QName secondName = second.getName(); - if (QNameUtil.match(firstName, AssignmentType.F_CONSTRUCTION) && - QNameUtil.match(secondName, ConstructionType.F_RESOURCE_REF)) { - return true; + JpaLinkDefinition link = findRawLinkDefinition(path.first(), JpaDataNodeDefinition.class); + if (link == null) { + return null; + } else { + link.resolveEntityPointer(); + return new DataSearchResult(link, path.tail()); } - return false; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java index 8aab6ffbce8..8d083f6b504 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java @@ -23,7 +23,10 @@ /** * Special placeholder to allow for cross-references: entity definition that points to another entity. - * (TODO) + * Currently, the process of resolving allows to point to root entity definitions here only. + * As a hack, we implement self pointers (e.g. RAssignment.metadata->RAssignment) also for non-root + * entities, provided they are resolved on creation. (The reason of using JpaEntityPointerDefinition + * there is just to break navigation cycles e.g. when using a visitor.) * * @author mederly */ @@ -35,6 +38,11 @@ public JpaEntityPointerDefinition(Class jpaClass) { super(jpaClass, null); } + public JpaEntityPointerDefinition(JpaEntityDefinition alreadyResolved) { + super(alreadyResolved.getJpaClass(), alreadyResolved.getJaxbClass()); + this.resolvedEntityDefinition = alreadyResolved; + } + public JpaEntityDefinition getResolvedEntityDefinition() { return resolvedEntityDefinition; } @@ -66,4 +74,8 @@ public String debugDump(int indent) { public void accept(Visitor visitor) { visitor.visit(this); } + + public boolean isResolved() { + return resolvedEntityDefinition != null; + } } From 4cab00b51b0b4f19e80c50974a4f93133b1eb472 Mon Sep 17 00:00:00 2001 From: honchar Date: Tue, 1 Dec 2015 10:27:48 +0100 Subject: [PATCH 044/116] MID-2741 is fixed --- .../com/evolveum/midpoint/web/security/MidPointApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java index f4d91cb95a3..4d057ee8dec 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java @@ -212,6 +212,7 @@ public void init() { getComponentInstantiationListeners().add(new SpringComponentInjector(this)); IResourceSettings resourceSettings = getResourceSettings(); + resourceSettings.setParentFolderPlaceholder("$-$"); resourceSettings.setHeaderItemComparator(new PriorityFirstComparator(true)); SecurePackageResourceGuard guard = (SecurePackageResourceGuard) resourceSettings.getPackageResourceGuard(); guard.addPattern("+*.woff2"); From 9459793e3a1746f0f627717f6881a2ac21c097f4 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 10:30:13 +0100 Subject: [PATCH 045/116] Fixing RichHyperlinkType authorizations (MID-2725) --- .../midpoint/web/page/self/component/LinksPanel.java | 3 +-- .../java/com/evolveum/midpoint/web/util/WebMiscUtil.java | 7 +++++++ .../initial-objects/020-system-configuration.xml | 2 ++ .../src/main/resources/xml/ns/public/common/common-3.xsd | 8 ++++---- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java index ca523d63dca..f7324496303 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java @@ -51,8 +51,7 @@ protected void initLayout() { WebMarkupContainer row = null; for (int i = 0; i < linksListSize; i++) { final RichHyperlinkType link = linksList.get(i); - String authorization = link.getAuthorization(); - if (authorization == null || WebMiscUtil.isAuthorized(authorization)) { + if (WebMiscUtil.isAuthorized(link.getAuthorization())) { if (currentColumn == 0) { row = new WebMarkupContainer(rowView.newChildId()); columnView = new RepeatingView(ID_LINKS_COLUMN); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java index 25c254e001b..d4af436056f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java @@ -141,6 +141,13 @@ public static boolean isAuthorized(String... action) { return true; } List actions = Arrays.asList(action); + return isAuthorized(actions); + } + + public static boolean isAuthorized(Collection actions) { + if (actions == null) { + return true; + } Roles roles = new Roles(AuthorizationConstants.AUTZ_ALL_URL); roles.addAll(actions); if (((AuthenticatedWebApplication) AuthenticatedWebApplication.get()).hasAnyRole(roles)) { diff --git a/gui/admin-gui/src/main/resources/initial-objects/020-system-configuration.xml b/gui/admin-gui/src/main/resources/initial-objects/020-system-configuration.xml index 83f43776acb..8ce3eed242d 100644 --- a/gui/admin-gui/src/main/resources/initial-objects/020-system-configuration.xml +++ b/gui/admin-gui/src/main/resources/initial-objects/020-system-configuration.xml @@ -104,6 +104,7 @@ blue http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfProfile + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll /self/credentials @@ -114,6 +115,7 @@ red http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfCredentials + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll /admin/users diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index d6b78c3ef10..c00e00292b4 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -8857,12 +8857,12 @@ - + - Authorization needed to display this link. If specified, the the link will be displayed - only if the active user has the authorization. If not specified then the link will be - always displayed. + Authorizations needed to display this link. If specified, the the link will be displayed + only if the active user has one of the specified the authorizations. + If no authorization is specified then the link will be always displayed. From 0a57c6401eac214c543b330233d16204daeb09d4 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 10:38:10 +0100 Subject: [PATCH 046/116] Switching off wicket devel mode --- gui/admin-gui/src/main/webapp/WEB-INF/web.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/admin-gui/src/main/webapp/WEB-INF/web.xml b/gui/admin-gui/src/main/webapp/WEB-INF/web.xml index 8b192b410b5..13f180a94d7 100644 --- a/gui/admin-gui/src/main/webapp/WEB-INF/web.xml +++ b/gui/admin-gui/src/main/webapp/WEB-INF/web.xml @@ -90,8 +90,8 @@ org.apache.wicket.protocol.http.WicketFilter configuration - development - + + deployment applicationBean From fada8af97e2d5f993c7f7ee82563249392ec13f9 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 10:41:49 +0100 Subject: [PATCH 047/116] CZ and DE translations from transifex (by Markus Steiner and Roman Pudil) --- .../localization/Midpoint_cs_CZ.properties | 314 +++++++++--------- .../localization/Midpoint_de_DE.properties | 116 +++---- 2 files changed, 215 insertions(+), 215 deletions(-) diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint_cs_CZ.properties b/gui/admin-gui/src/main/resources/localization/Midpoint_cs_CZ.properties index e8012ecd59a..6a5719b762c 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint_cs_CZ.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint_cs_CZ.properties @@ -14,7 +14,7 @@ # limitations under the License. # AbstractRoleType.identifier=Identifikátor -# AbstractRoleType.policyConstraints=Policy constraints +AbstractRoleType.policyConstraints=Politiky omezení ACAttributePanel.button.showExprEditor=Zobrazit výraz ACAttributePanel.hasOutbound=Má odchozí ACAttributePanel.required=Povinný @@ -50,7 +50,7 @@ AEPlevel.LEGALIZE=Relativní AEPlevel.MARK=Označený AEPlevel.NONE=Žádný AEPlevel.POSITIVE=Pozitivní -# assignablePopupContent.button.assign=Assign +assignablePopupContent.button.assign=Přiřazení assignablePopupContent.button.add=Vložit assignablePopupContent.description=Popis assignablePopupContent.displayName=Zobrazované jméno @@ -77,7 +77,7 @@ AssignmentEditorPanel.showEmpty=Zobrazit prázdné AssignmentEditorPanel.showMore=Zobrazít více AssignmentEditorPanel.targetError=Cíl přiřazení nebyl nalezen. Cílové OID je chybné nebo neexistuje cílový objekt. AssignmentEditorPanel.target=Cíl -AssignmentEditorPanel.tenantRef=Tenant +AssignmentEditorPanel.tenantRef=Držitel AssignmentPolicyEnforcementType.FULL=Plný AssignmentPolicyEnforcementType.LEGALIZE=Legalizovat AssignmentPolicyEnforcementType.MARK=Označit @@ -90,22 +90,22 @@ AssignmentPreviewDialog.column.intent=Záměr AssignmentPreviewDialog.column.kind=Typ AssignmentPreviewDialog.column.name=Název AssignmentPreviewDialog.column.orgRef=Organizace -AssignmentPreviewDialog.column.tenant=Tenant -AssignmentPreviewDialog.label=Prohlížní přímých i nepřímých přiřazení +AssignmentPreviewDialog.column.tenant=Držitel +AssignmentPreviewDialog.label=Zobrazit přímá i nepřímá přiřazení AssignmentPreviewDialog.type.direct=Přímé AssignmentPreviewDialog.type.indirect=Nepřímé AssignmentTablePanel.menu.assign=Přiřadit účet aplikace AssignmentTablePanel.menu.assignOrg=Přiřadit organizaci AssignmentTablePanel.menu.assignRole=Přiřadit roli AssignmentTablePanel.menu.unassign=Zrušit přiřazení -# AssignmentTablePanel.menu.showAllAssignments=Show all assignments +AssignmentTablePanel.menu.showAllAssignments=Zobrazit všechna přiřazení AssignmentTablePanel.message.couldntAssignObject=Nemohu přiřadit objekt '{0}', důvod\: {1}. AssignmentTablePanel.message.illegalAssignmentState=Nepovolený stav přiřazení '{0}'. AssignmentTablePanel.message.noAssignmentSelected=Není vybrané přiřazení. AssignmentTablePanel.modal.message.delete=Opravdu chcete smazat těchto {0} přiřazení? AssignmentTablePanel.modal.title.confirmDeletion=Potvrdit smazání AssignmentTablePanel.modal.title.selectAssignment=Vybrat objekty -AssignmentType.tenant=Tenant +AssignmentType.tenant=Držitel AssignmentType.project=Org. jednotka/projekt associationAttribute.nullValid=Vyberte jeden AsyncDashboardPanel.loading=Načítám data @@ -166,7 +166,7 @@ capabilityActivationPanel.list.placeholder=Vložit hodnotu capabilityCredentialsPanel.label=Konfigurace pověření capabilityCredentialsPanel.label.enabled=Povolený capabilityCredentialsPanel.label.password=Heslo -capabilityCredentialsPanel.label.returned=Vrátit ve výchozím nastavení +capabilityCredentialsPanel.label.returned=Vráceno jako výchozí capabilityListRepeater.label.text.placeholder=URL jazyka capabilityScriptPanel.label.enabled=Povolený capabilityScriptPanel.label.onConnector=Na konektoru @@ -229,7 +229,7 @@ chooseTypeDialog.button.cancel=Zrušit chooseTypeDialog.column.name=Název chooseTypeDialog.message.queryError=Chyba při překladu vyhledávacího dotazu do filtru. chooseTypeDialog.title=Vybrat objekt -chooseTypePanel.ObjectNameValue.badOid=(nájemce nenalezen) +chooseTypePanel.ObjectNameValue.badOid=(držitel nenalezen) chooseTypePanel.ObjectNameValue.null=Žádný com.evolveum.midpoint.notifications.api.transports.MailTransport.send=Send mail (Notifications) com.evolveum.midpoint.notifications.api.transports.SimpleSmsTransport.send=Send SMS (Notifications) @@ -276,7 +276,7 @@ DeltaPanel.label.objectToAdd=Vkládané objekty\: DeltaPanel.label.oid=Objekt s oid\: direction.nullvalid=Vyberte jeden DoubleButtonPanel.button.default=Spustit -# DoubleButtonPanel.download=Download +DoubleButtonPanel.download=Stáhnout DropDownChoicePanel.empty=Vyberte jeden DropDownChoicePanel.notDefined=Nedefinovaný EmptyProcessDetailsPanel.message=Detaily procesu nejsou k dispozici. @@ -357,7 +357,7 @@ filter.emptyFilter=Filter nesmí být prázdný FocusType.activation=Aktivace FocusType.assignment=Přiřazení FocusType.inducement=Dědění -# FocusType.displayName=Display Name +FocusType.displayName=Zobrazené jméno H3Header.label.error=Chyba H3Header.showMore=Více HandlerUriActions.ACTION_ADD_ACCOUNT=Vložit účet @@ -408,11 +408,11 @@ JasperReportConfigurationPanel.fieldName=Název položky JasperReportConfigurationPanel.forPrompting=Pro dotazování JasperReportConfigurationPanel.parameterClass=Třída parametru JasperReportConfigurationPanel.parameterName=Název parametru -# JasperReportConfigurationPanel.parameterProperty=Property\: {0} +JasperReportConfigurationPanel.parameterProperty=Vlastnost\: {0} JasperReportConfigurationPanel.reportFields=Položky reportu JasperReportConfigurationPanel.reportParameters=Parametry reportu JasperReportConfigurationPanel.reportQuery=Dotaz reportu -# JasperReportConfigurationPanel.errormsg=Empty values not allowed +JasperReportConfigurationPanel.errormsg=Prázdné hodnoty nejsou povoleny kind.nullValid=Vyberte jeden Language.GROOVY=Groovy (výchozí) Language.JAVASCRIPT=Javascript @@ -635,8 +635,8 @@ objectSyncConfig.editorObjectTemplate.nullValid=Vyberte jeden objectTemplateRef.nullValid=Vyberte jeden ObjectType.description=Popis ObjectTypeGuiDescriptor.abstractRole=Abstraktní role -# ObjectTypeGuiDescriptor.accessCertificationCampaign=Access certification campaign -# ObjectTypeGuiDescriptor.accessCertificationDefinition=Access certification definition +ObjectTypeGuiDescriptor.accessCertificationCampaign=Kampaň certifikace přístupů +ObjectTypeGuiDescriptor.accessCertificationDefinition=Definice certifikace přístupů ObjectTypeGuiDescriptor.account=Účet ObjectTypeGuiDescriptor.connector=Konektor ObjectTypeGuiDescriptor.connectorHost=Konektor host @@ -653,7 +653,7 @@ ObjectTypeGuiDescriptor.report=Report ObjectTypeGuiDescriptor.resource=Aplikace ObjectTypeGuiDescriptor.role=Role ObjectTypeGuiDescriptor.securityPolicy=Bezpečnostní politika -# ObjectTypeGuiDescriptor.sequence=Sequence +ObjectTypeGuiDescriptor.sequence=Sekvence ObjectTypeGuiDescriptor.shadow=Shadow ObjectTypeGuiDescriptor.systemConfiguration=Systémová konfigurace ObjectTypeGuiDescriptor.task=Úloha @@ -662,7 +662,7 @@ ObjectTypeGuiDescriptor.valuePolicy=Politika hodnot ObjectType.name=Název ObjectType.parentOrgRef=Nadřazené org. jednotky operation.com.evolveum.midpoint.common.crypto.CryptoUtil.securitySelfTest=Security self test -operation.com.evolveum.midpoint.common.operation.import.object=Import object +operation.com.evolveum.midpoint.common.operation.import.object=Importovat objekt operation.com.evolveum.midpoint.common.policy.PasswordPolicyUtils.passwordValidation=Password validation against password policy operation.com.evolveum.midpoint.common.validator.Validator.objectBasicsCheck=Basic checks operation.com.evolveum.midpoint.common.validator.Validator.resourceNamespaceCheck=Resource namespace check @@ -955,7 +955,7 @@ OrgType.locality=Lokalita OrgType.mailDomain=Mailová doména OrgType.orgType=Typ organizace OrgType.requestable=Lze žádat -OrgType.tenant=Tenant +OrgType.tenant=Držitel orgUnitAddDeletePopup.button.add=Vložit org. jednotku orgUnitAddDeletePopup.button.cancel=Zrušit orgUnitAddDeletePopup.button.remove=Smazat org. jednotku @@ -1064,8 +1064,8 @@ PageAdmin.menu.top.configuration.expressionEvaluator=Kalkulátor výrazů PageAdmin.menu.top.configuration.importObject=Import objektů PageAdmin.menu.top.configuration.internals=Interní konfigurace PageAdmin.menu.top.configuration.logging=Logování -# PageAdmin.menu.top.configuration.notifications=Notifications -# PageAdmin.menu.top.configuration.profiling=Profiling +PageAdmin.menu.top.configuration.notifications=Notifikace +PageAdmin.menu.top.configuration.profiling=Profiling PageAdmin.menu.top.configuration.repositoryObjects=Objekty v repozitory PageAdmin.menu.top.configuration.security=Bezpečnost PageAdmin.menu.top.configuration.shadowsDetails=Stínové účty @@ -1095,7 +1095,7 @@ PageAdmin.menu.top.workItems.listClaimable=Úkoly nárokované na mě PageAdmin.menu.top.workItems.list=Moje úkoly PageAdmin.menu.top.workItems.listProcessInstancesAll=Všechny požadavky PageAdmin.menu.top.workItems.listProcessInstancesRequestedBy=Moje požadavky -PageAdmin.menu.top.workItems.listProcessInstancesRequestedFor=Požadavky o mě +PageAdmin.menu.top.workItems.listProcessInstancesRequestedFor=Požadavky o mně PageAdmin.menu.top.workItems=Úkoly a požadavky pageAdmin.reports.description=Exportovat reporty pageAdmin.reports=Reporty @@ -1107,34 +1107,34 @@ pageAdminFocus.subTitle.editOrgType=organizace '{0}' pageAdminFocus.subTitle.newOrgType=nová organizace pageAdminFocus.title.editFocusType=Upravit pageAdminFocus.title.newFocusType=Vytvořit -# pageAdminFocus.message.illegalAccountState=Illegal shadow state '{0}'. -# pageAdminFocus.message.illegalAccountState=Illegal shadow state '{0}'. +pageAdminFocus.message.illegalAccountState=Nelegální stav stínového účtu '{0}'. +pageAdminFocus.message.illegalAccountState=Nelegální stav stínového účtu '{0}'. pageAdminFocus.message.noAssignmentsAvailable=Není zde žádné přiřazení pro zobrazení. -# pageAdminFocus.message.noOrgSelected=No organization was selected. -# pageAdminFocus.menu.assignShadow=Assign resource +pageAdminFocus.message.noOrgSelected=Nebyla vybrána žádná organizace. +pageAdminFocus.menu.assignShadow=Přiřadit aplikaci pageAdminFocus.menu.assignRole=Přiřadit roli pageAdminFocus.menu.assignOrg=Přiřadit org. jednotku pageAdminFocus.menu.unassign=Zrušit přiřazení -# pageAdminFocus.button.addShadow=Add projection +pageAdminFocus.button.addShadow=Přidat projekci pageAdminFocus.button.enable=Povolit pageAdminFocus.button.disable=Zakázat pageAdminFocus.button.unlink=Odpojit pageAdminFocus.button.unlock=Odemknout pageAdminFocus.button.delete=Smazat -# pageAdminFocus.button.addToOrg=Add to organization +pageAdminFocus.button.addToOrg=Přidat do organizace pageAdminFocus.focusDetails=Detaily pageAdminFocus.projections=Projekce -# pageAdminFocus.organizations=Organizations +pageAdminFocus.organizations=Organizace # pageAdminFocus.message.couldntCreateAccountNoSchema=Couldn't create projection form for '{0}', no refined schema available. Possible problem with connector configuration and/or connection. Please check logs for more information. # pageAdminFocus.message.couldntCreateAccountNoAccountSchema=Couldn't create projection form for '{0}', no schema for default 'account' object type available. Possible problem with resource configuration. Please check logs for more information. -# pageAdminFocus.message.couldntCreateAccount=Couldn't create projection form for '{0}', reason\: {1}. +pageAdminFocus.message.couldntCreateAccount=Nemohu vytvořit formulář projekce pro '{0}', důvod\: {1}. pageAdminFocus.message.noAssignableSelected=Není vybrané přiřazení. pageAdminFocus.message.couldntAssignObject=Nemohu přiřadit objekt '{0}', důvod\: {1}. -# pageAdminFocus.message.noActivationFound=No activation found for projection '{0}'. +pageAdminFocus.message.noActivationFound=Pro projekci '{0}' nebyla nalezena žádná aktivace. pageAdminFocus.message.noEnabledPropertyFound=Nenalezena vlastnost enabled pro účet '{0}'. -# pageAdminFocus.message.noAccountSelected=No projection selected. +pageAdminFocus.message.noAccountSelected=Nebyla zvolena žádná projekce. pageAdminFocus.message.noAssignmentSelected=Není vybrané přiřazení. -# pageAdminFocus.title.selectResource=Select resource(s) +pageAdminFocus.title.selectResource=Vybrat aplikace pageAdminFocus.title.selectAssignable=Vybrat objekty pageAdminFocus.task.name=Název úlohy pageAdminFocus.task.category=Kategorie @@ -1144,7 +1144,7 @@ pageAdminFocus.button.save=Uložit pageAdminFocus.button.abort=Přerušit pageAdminFocus.button.back=Zpět pageAdminFocus.title.confirmDelete=Potvrdit smazání -# pageAdminFocus.message.deleteAccountConfirm=Do you really want to delete {0} projection(s)? +pageAdminFocus.message.deleteAccountConfirm=Opravdu chcete smazat {0} projekcí? pageAdminFocus.message.deleteAssignmentConfirm=Opravdu chcete smazat těchto {0} přiřazení? pageAdminResources.accountDetails=Detaily účtu pageAdminResources.contentAccounts=Účty @@ -1176,7 +1176,7 @@ PageBase.button.search=Hledat PageBase.button.send=Odeslat PageBase.button.update=Aktualizovat PageBase.clearCssCache=Vyčistit less/js cache -# pageBase.midPointVersion=${pom.version}, ${describe} +pageBase.midPointVersion=${pom.version}, ${describe} pageBase.unknownBuildNumber=neznámý PageBulkAction.async=Asynchronní PageBulkAction.button.start=Start @@ -1247,7 +1247,7 @@ PageCertCampaign.statistics.response=Odpověď PageCertCampaign.statistics.revokeRemedied=Odmítnout - remediováno PageCertCampaign.statistics.revoke=Odmítnout PageCertCampaign.statistics=Statistika -# PageCertCampaigns.title=Access Certification Campaigns +PageCertCampaigns.title=Kampaně certifikace přístupů PageCertCampaign.subTitle= PageCertCampaign.table.campaignName=Název kampaně PageCertCampaign.table.comments=Komentáře @@ -1261,7 +1261,7 @@ PageCertCampaign.table.reviewedBy=Ověřil PageCertCampaign.table.reviewedInStage=Ve fázi PageCertCampaign.table.targetName=Cíl PageCertCampaign.time=Čas -# PageCertCampaign.title=Access Certification Campaign +PageCertCampaign.title=Kampaň certifikace přístupů PageCertDecisions.ago=před {0} PageCertDecisions.checkbox.showNoResponseOnly=Zobrazit pouze záznamy "bez odpovědi" PageCertDecisions.in=za {0} @@ -1306,11 +1306,11 @@ PageCertDefinitions.deleteDefinitionConfirmSingle=Opravdu chcete smazat definici PageCertDefinitions.subTitle=volné PageCertDefinitions.table.description=Popis PageCertDefinitions.table.name=Název -# PageCertDefinitions.title=Access Certification Definitions +PageCertDefinitions.title=Definice certifikací přístupů PageCertDefinitions.title.confirmDelete=Potvrdit smazání PageCertDefinition.subTitle= PageCertDefinitionsxmlDefinition=XML definice -# PageCertDefinition.title=Access Certification Campaign Definition +PageCertDefinition.title=Definice kampaně certifikace přístupů PageCertDefinition.xmlDefinition=XML definice PageCert.in=za {0} PageCert.message.assignment={0} z {1} {2} až {3} {4}. @@ -1324,7 +1324,7 @@ PageCert.message.textKind=Typ\: {0}. PageCert.message.textOrder=Pořadí\: {0}. PageCert.message.textOrg=Organizace\: {0}. PageCert.message.textRelation=Vazba\: {0}. -# PageCert.message.textTenant=Tenant\: {0}. +PageCert.message.textTenant=Držitel\: {0}. PageCert.message.textValidFrom=Platný od\: {0}. PageCert.message.textValidTo=Platný do\: {0}. PageCert.now=Nyní @@ -1563,7 +1563,7 @@ PageMyPasswords.button.back=Zpět PageMyPasswords.button.save=Uložit PageMyPasswords.couldntResolve=Nemohu kontaktovat aplikaci. PageMyPasswords.enabled=Povoleno -# PageMyPasswords.importantNote=If selected, user password and all accounts' credentials will be updated based on policies defined in resources definitions. +PageMyPasswords.importantNote=Pokud je vybráno, pak jsou uživatelské heslo a všechna pověření účtů uživatele aktualizována podle nastavení politik v definici aplikací. PageMyPasswords.name=Název PageMyPasswords.noAccountSelected=Heslo nebylo změněno, nebyla vybrána žádná aplikace. PageMyPasswords.password=Dvakrát nové heslo @@ -1592,7 +1592,7 @@ PageOrgUnit.title.assignments=Přiřazení PageOrgUnit.title.authorizations=Autorizace PageOrgUnit.title.basic=Základní PageOrgUnit.title.exclusions=Výjimky -# PageOrgUnit.title.inducements=Inducements +PageOrgUnit.title.inducements=Dědění PageOrgUnit.title=Nová org. jednotka PageOrgUnit.title.parentOrgUnit=Nadřazený pageProcessInstance.button.back=Zpět @@ -1613,7 +1613,7 @@ pageProcessInstances.notYet=Ještě ne PageProcessInstancesRequestedBy.title=Procesy s mými žádostmi PageProcessInstancesRequestedFor.title=Procesy se žádostmi o mě PageProcessInstance.title=Detaily procesu -# PageReport.basic=Configuration +PageReport.basic=Konfigurace PageReport.fullXml=Plné XML PageReport.jasperTemplate=Šablona Jasper PageReport.jasperTemplateStyle=Styl šablony Jasper @@ -1632,11 +1632,11 @@ PageReports.report.reconciliationName=Rekonciliace PageReports.report.usersDescription=Seznam uživatelů v MidPointu. PageReports.report.usersName=Uživatelé v MidPointu PageReports.search.showSubreports=Zobrazit podreporty -# PageReports.subTitle=in midPoint +PageReports.subTitle=v midPointu PageReports.table.description=Popis PageReports.table.name=Název PageReports.title.auditPopup=Parametry auditního reportu -# PageReports.title=Available reports +PageReports.title=Dostupné reporty PageReports.title.reconciliationPopup=Parametry reportu rekonciliace PageReports.title.userPopup=Parametry uživatelského reportu PageReport.title=Konfigurace reportu @@ -1671,7 +1671,7 @@ pageResource.overallStatus=Celkový stav pageResource.progress=Zpracování pageResource.resource=Aplikace pageResources.bundle=Balík -# pageResources.connectorType=Connector type +pageResources.connectorType=Typ konektoru pageResources.button.discoveryRemote=Prozkoumat pageResources.button.editAsXml=Upravit jako XML pageResources.button.search=Hledat @@ -1698,7 +1698,7 @@ pageResources.progress=Zpracování pageResources.resources=Aplikace pageResources.searchText.placeholder=Název pageResources.status=Poslední stav -PageResources.subTitle=připojení do midPointu +PageResources.subTitle=připojeno do midPointu pageResource.status=Stav PageResources.title=Aplikace pageResources.version=Verze @@ -1748,15 +1748,15 @@ PageSecurityQuestions.title=Bezpečnostní otázky PageShowPassword.message=Vaše nové heslo\: PageShowPassword.success=Nové heslo bylo úspěšně vytvořeno PageShowPassword.title=Nové heslo -# PageSizePopover.title=Page size +PageSizePopover.title=Velikost stránky pageSystemConfiguration.assignmentPolicyEnforcement.value.full=Plný pageSystemConfiguration.assignmentPolicyEnforcement.value.legalize=Relativní pageSystemConfiguration.assignmentPolicyEnforcement.value.mark=Označený pageSystemConfiguration.assignmentPolicyEnforcement.value.none=Žádný pageSystemConfiguration.assignmentPolicyEnforcement.value.positive=Pozitivní pageSystemConfiguration.logging.title=Logování -# pageSystemConfiguration.notifications.title=Notifications -# pageSystemConfiguration.profiling.title=Profiling +pageSystemConfiguration.notifications.title=Notifikace +pageSystemConfiguration.profiling.title=Profilaxe PageSystemConfiguration.subTitle=pro midPoint pageSystemConfiguration.system.title=Systém PageSystemConfiguration.title=Konfigurace @@ -1781,7 +1781,7 @@ pageTask.cronHelpLink=Pro více informací viz pageTask.cronHelpLinkTutorial=návod pageTask.cronSpec=Plánování spouštění pageTask.dryRun=Spustit nanečisto -# pageTask.focusType=Applicable to type +pageTask.focusType=Vztahuje se k typu pageTaskEdit.basic=Základní pageTaskEdit.boundHelp=Úlohy s pevnou vazbou jsou používány pro krátké a často se opakující akce (např. v intervalech menších než 1 minuta). Typickým příkladem je live synchronizace. Tyto úlohy nepodporují cron-like specifikaci; musíte specifikovat časový interval. pageTaskEdit.bound=Pevná vazba (použijte v případě, že úloha běží často) @@ -1806,7 +1806,7 @@ pageTaskEdit.kind=Typ objektu pageTaskEdit.lastFinished=Poslední běh ukončen pageTaskEdit.lastStarted=Poslední běh spuštěn pageTaskEdit.message.cantTaskDetails=Nemohu načíst detaily úlohy. -pageTaskEdit.message.node=- v node {0} +pageTaskEdit.message.node=- v uzlu {0} pageTaskEdit.misfire=Selhání akce pageTaskEdit.modelOperationStatusLabel=Stav operace modelu pageTaskEdit.name=Název úlohy @@ -1866,7 +1866,7 @@ pageTasks.button.stopSchedulerAndTasks=Zastavit plánovač a úlohy pageTasks.button.stopScheduler=Zastavit plánovač pageTasks.button.suspendTask=Pozastavit pageTasks.button.synchronizeTasks=Synchronizovat úlohy -# pageTasks.category.AccessCertification=Access certification +pageTasks.category.AccessCertification=Certifikace přístupu pageTasks.category.AllCategories=Všechny kategorie pageTasks.category.BulkActions=Hromadné akce pageTasks.category=Kategorie @@ -1883,7 +1883,7 @@ pageTasks.category.System=Systém pageTasks.category.UserRecomputation=Přepočítání uživatelů pageTasks.category.Utility=Utilita pageTasks.category.Workflow=Úkoly a požadavky -# pageTasks.category.ExecuteChanges=Execute changes +pageTasks.category.ExecuteChanges=Provést změny pageTask.scheduleHelp=Pro jednorázové úlohy nenastavujte interval opakování ani cron-like specifikaci. Pro opakující se úlohy nastavte buď jedno nebo druhé. pageTask.scheduleInterval=Interval spouštění (sekundy) pageTask.scheduleTitle=Plánování @@ -1912,7 +1912,7 @@ pageTasks.node.statusMessage=Stavová zpráva pageTasks.nowForNotRunningTasks=(nyní) pageTasks.now=Nyní pageTasks.runsContinually=běží nepřetržitě -pageTasks.stalledSince=ZASTAVENO od {0} do {1} +pageTasks.stalledSince=POZASTAVENO od {0} v {1} pageTasks.state=Stav pageTasks.subtasks=Zobrazit podúlohy PageTasks.subTitle=v midPointu @@ -1950,7 +1950,7 @@ pageUser.button.save=Uložit pageUser.button.submit=Prohlédnout změny pageUser.button.unlink=Odpojit pageUser.button.unlock=Odemknout -pageUser.description=uživatelé v repozitory +pageUser.description=Uživatel v repozitory pageUser.menu.assignAccount=Přiřadit účet pageUser.menu.assignOrg=Přiřadit org. jednotku pageUser.menu.assignRole=Přiřadit roli @@ -2049,8 +2049,8 @@ pageWorkItem.trackingData.description=Sledování (diagnostika) dat pageWorkItem.trackingData=Sledování dat pageWorkItem.workItemCreatedOn=Úkol vytvořen\: passwordPanel.error=Hesla nejsou shodná. -# passwordPanel.passwordChange=Change -# passwordPanel.passwordSet=password is set +passwordPanel.passwordChange=Změna +passwordPanel.passwordSet=Heslo je nastaveno past.ChangeType.ADD=Vloženo past.ChangeType.DELETE=Smazáno past.ChangeType.MODIFY=Upraveno @@ -2061,7 +2061,7 @@ PersonalInfoPanel.lastLogin.date=Datum PersonalInfoPanel.lastLogin.from=Počítač PersonalInfoPanel.lastLogin=Poslední přihlášení PersonalInfoPanel.never=Nikdy -# PersonalInfoPanel.other=Other +PersonalInfoPanel.other=Ostatní PersonalInfoPanel.passwordExp=Datum expirace účtu PersonalInfoPanel.undefined=Není nastaveno PolicyConstraintEnforcementType.ENFORCE=Vynutit @@ -2069,7 +2069,7 @@ PolicyConstraintEnforcementType.REMEDIATE=Napravit PolicyConstraintEnforcementType.REPORT=Oznámit policyRef.nullValid=Vyberte jeden PrismObjectPanel.hideEmpty=Skrýt prázdné položky -# PrismObjectPanel.maximize=Maximize +PrismObjectPanel.maximize=Maximalizovat PrismObjectPanel.minimize=Minimalizovat PrismObjectPanel.protectedAccount=Chráněný účet PrismObjectPanel.showEmpty=Zobrazit prázdné položky @@ -2091,7 +2091,7 @@ processInstancePanel.message.noTasks=žádný processInstancePanel.name=Název procesu\: processInstancePanel.pid=ID instance\: processInstancePanel.started=Spuštěno\: -# processInstancePanel.taskAlreadyRemoved=(was already removed) +processInstancePanel.taskAlreadyRemoved=(byl již odebrán) processInstancePanel.task=Úloha MidPointu\: processInstancePanel.tasks=Aktuální aktivní úkoly\: processInstancePanel.title.edit=Detaily pro '{0}' @@ -2132,21 +2132,21 @@ QNameEditor.tooltip.attribute=TODO\: QNameEditor.tooltip.attribute QNameEditor.tooltip.localPart=Lokální část QName QNameEditor.tooltip.namespace=Prostor názvů QName RangeValidator.range=Položka '${label}' musí být mezi ${minimum} a ${maximum}. -# ReconciliationPopupPanel.exportFileType=Export Type -# DownloadButtonPanel.download=Download +ReconciliationPopupPanel.exportFileType=Typ exportu +DownloadButtonPanel.download=Stáhnout ReconciliationPopupPanel.resource=Aplikace ReconciliationPopupPanel.title.basic=Základní konfigurace reportů rekonciliace repeater.input.nullValid=Vyberte jeden ReportConfigurationPanel.title.basic=Základní -# ReportConfigurationPanel.title.advanced=Advanced +ReportConfigurationPanel.title.advanced=Rozšířený ReportType.export=Exportovat ReportType.orientation=Orientace ReportType.parent=Nadřazený ReportType.useHibernateSession=Použít hibernate sezení -# ReportType.virtualizer=Jasper virtualizer +ReportType.virtualizer=Jasper virtualizer # ReportType.virtualizerKickOn=Virtualizer's pages kick-on -# ReportType.maxPages=Maximum number of pages -# ReportType.timeout=Execution timeout [ms] +ReportType.maxPages=Maximální počet stránek +ReportType.timeout=Maximální čas zpracování [ms] Requestable.ALL=Vše Requestable.NON_REQUESTABLE=Nelze žádat Requestable.REQUESTABLE=Lze žádat @@ -2230,14 +2230,14 @@ ResourceIterationEditor.label.variable=Proměnná resource.nullValid=Vybrat aplikaci ... ResourceObjectAssociationDirectionType.OBJECT_TO_SUBJECT=Objekt do subjetu ResourceObjectAssociationDirectionType.SUBJECT_TO_OBJECT=Subjekt do objektu -ResourceObjectTypeDependencyStrictnessType.LAX=Velmni mírná +ResourceObjectTypeDependencyStrictnessType.LAX=Velmi mírná ResourceObjectTypeDependencyStrictnessType.RELAXED=Mírná ResourceObjectTypeDependencyStrictnessType.STRICT=Přísná resourcePopup.bundle=Balík -# resourcePopup.button.add=Add resource(s) +resourcePopup.button.add=Přidat aplikaci(e) resourcePopup.name=Název resourcePopup.version=Verze -# ResourceProtectedEditor.button.add=Add protected account +ResourceProtectedEditor.button.add=Přidat chráněný účet ResourceProtectedEditor.label.description=Popis ResourceProtectedEditor.label=Upravit chráněné účty ResourceProtectedEditor.label.filterClause=Člen filtru @@ -2259,7 +2259,7 @@ ResourceWizard.help.configurationStep=

This stage of the wizard configures con ResourceWizard.help.nameStep=

This stage of the wizard configures basic properties of the resource. It can be used to configure resource name and description. Connector name is mandatory and must be unique. Connector that will be used to access the resource must also be configured. Connectors are deployed on connector hosts. If the connector host is left empty then connectors deployed directly in the midPoint instance will be used.

See Resource Configuration wiki page for detailed explanation of resource configuration.

ResourceWizard.help.schemaHandlingStep=

This step is used to provide configuration for handling of resource schema. The configuration displayed on this page tells midPoint what to do with resource object classes and attributes. It contains the configuration of mappings between user properties and account attributes, configuration of account types, groups, provisioning dependencies, password mapping and so on.

The configuration is grouped into object types. Each object type defines the behavior for specific account type, entitlement type, OU, etc. The object type is uniquely identified by the combination of kind and intent. The kind defines what kind of the object it is\:

  • kind\=account means that the object is an account, i.e. that it represents a user.
  • kind\=entitlement is applied to groups, roles, privileges, ACIs and similar objects that can be associated with accounts and which give privileges or access rights to the account.
  • kind\=generic applies to other objects such as organizational units (OUs), domains, etc.
Intent is a plain string that can be used to distinguish several object types. E.g. it can be used to define several account type, e.g. "default user account", "administration account", "testing account" and so on. See Kind, Intent and ObjectClass wiki page for more details.

More details about schema handling configuration are provided on Resource Schema Handling wiki page. ResourceWizard.help.schemaStep=

This page shows resource schema. The resource schema defines object classes that the connector can manage, e.g. accounts, groups, organizational units and so on. The schema defines a set of attributes for each object class. The schema is presented here in read-only form so you can inspect it and familiarize yourself with the data model that the resource provides.

The resource schema presented at this page is usually retrieved from the resource and automatically generated by midPoint. Resource schema defines what the resource can do, i.e. what object classes it defines and what attributes are used in the object classes. Therefore the schema is read-only. It is not a configuration. It does not defines how midPoint uses the object classes and attributes. That is configured in next steps of the wizard.

See Resource Schema wiki page for detailed explanation of resource schema concepts

-# ResourceWizard.help.synchronizationStep=

The synchronization configuration defines how midPoint reacts when it discovers that resource object has changed. E.g. it defines how midPoint reacts when it discovers new account, when it discovers that a group that should exist does not and so on. It is usually does not matter how midPoint discovers the change the reaction is usually the same (although exceptions are possible by using channel specification). Therefore the policy that is configured here usually applies to live synchronization, reconciliation, import, discovery (consistency mechanism) and possible also other mechanisms that may come in the future.

See Synchronization Configuration wiki page for more details. +ResourceWizard.help.synchronizationStep=

Konfigurace synchronizace definuje, jak bude midPoint reagovat, když zjistí, že se objekt v aplikaci změnil. Např. definuje, jak bude midPoint reagovat, když zjistí nový účet, když zjistí, že skupina, která by měla existovat již neexistuje, atd. Obvykle nezáleží na tom, jak Midpoint zjistí změnu, reakce se víceméně stejná (i když existují výjimky na základě specifikace aplikace ). Proto politika nakonfigurována zde obvykle platí pro live synchronizace , rekonciliaci , import , průzkum (mechanismus konzistence) a další mechanismy, které mohou přijít v budoucnu.

Viz Synchronizace konfigurace wiki stránka pro více informací. runReportPopupContent.button.run=Spustit report runReportPopupContent.param.class=Třída parametru runReportPopupContent.param.name.eventStage = Fáze události @@ -2268,7 +2268,7 @@ runReportPopupContent.param.name.from = Datum od runReportPopupContent.param.name.initiatorName = Jméno iniciátora runReportPopupContent.param.name.outcome = Výsledek runReportPopupContent.param.name=Název parametru -# runReportPopupContent.param.name.targetName = Target Name +runReportPopupContent.param.name.targetName = Cílový název runReportPopupContent.param.name.to = Datum do runReportPopupContent.param.value=Hodnota parametru RunReportPopupPanel.title=Konfigurace reportu před spuštěním @@ -2281,7 +2281,7 @@ SchemaHandlingStep.association.label.associationName=Název asociace SchemaHandlingStep.association.label.associationNamespace=Prostor názvů asociace SchemaHandlingStep.association.tooltip.associationAttribute=Name of the attribute that "holds" the association. I.e. an attribute which contains the identifier of the associated object. This is usually an attribute such as "memeber", "groups", "roles", etc. In subject-to-object associations this is an attribute of a subject (e.g. account attribute "groups"). In object-to-subject associations this is an attribute of an object (e.g. group attribute "members"). SchemaHandlingStep.association.tooltip.associationLocalPart=TODO\: SchemaHandlingStep.association.tooltip.associationLocalPart -# SchemaHandlingStep.association.tooltip.associationNamespace=TODO\: SchemaHandlingStep.association.tooltip.associationNamespace +SchemaHandlingStep.association.tooltip.associationNamespace=TODO\: SchemaHandlingStep.association.tooltip.associationNamespace SchemaHandlingStep.association.tooltip.direction=Defines the direction of the association. Object-to-subject\: Object (e.g. group) has an attribute that contains identifier of the subject (e.g. account); Subject-to-object\: Subject (e.g. account) has an attribute that contains identifier of the object (e.g. group). SchemaHandlingStep.association.tooltip.explicitRefIntegrity=Explicit referential integrity. If set to false then midPoint assumes that the resource implements referential integrity. E.g. midPoint assumes that the resource automatically updates the association identifiers if an account is renamed and midPoint does not need to do anything. If set to true then midPoint will do referential integrity explicitly. In this case midPoint will explicitly update the association attributes if an account is renamed. SchemaHandlingStep.association.tooltip.intent=Intent of the association target object type. Target kind and intent identify an object type which is association target, e.g. a group, privilege, role, etc. @@ -2376,7 +2376,7 @@ SchemaHandlingStep.tooltip.kind=Kind specified what this object is, whether it i SchemaHandlingStep.tooltip.objectClass=Object class from the schema that will be used to construct instances of this object type. SchemaHandlingStep.tooltip.protected=Specification of protected instances of this object type. MidPoint can see protected instances but they cannot be touched. Any attempt to modify them will fail. This is used to protect emergency administration accounts such as "root" or "administrator". SchemaListPanel.attributes=Atributy -# SchemaListPanel.details.default=Default +SchemaListPanel.details.default=Výchozí SchemaListPanel.details.description=Popis SchemaListPanel.details=Detaily SchemaListPanel.details.displayName=Zobrazené jméno @@ -2405,7 +2405,7 @@ SearchFilterPanel.button.update=Aktualizovat SearchFilterPanel.label.description=Popis SearchFilterPanel.label.filterClause=Filtrovat SearchFilterPanel.message.cantSerialize=Nemohu vytvořit MaxXNode z poskytnutého XML filtru. Vložte správnou hodnotu. Důvod\: {0} -# SearchFilterPanel.message.expressionSuccess=Filter clause has been update successfully. +SearchFilterPanel.message.expressionSuccess=Definice filtru byla úspěšně aktualizována. searchForm.filetype.null=Typ souboru searchForm.reportType.null=Typ reportu searchForm.searchTextPlaceholder=Text @@ -2418,7 +2418,7 @@ SearchType.NAME=Jméno ShadowKindType.ACCOUNT=Účet ShadowKindType.ENTITLEMENT=Skupina/Role ShadowKindType.GENERIC=Obecný -# simpleErrorPanel.label.showMore=Show more +simpleErrorPanel.label.showMore=Zobrazit více simpleErrorPanel.message.error=Účet z aplikace '{0}' nebyl načten. situation.nullValid=Vyberte jeden StandardLoggerType.CHANGE_EXECUTOR=Change executor (c.e.m.model.impl.lens.ChangeExecutor) @@ -2455,17 +2455,17 @@ SynchronizationInformationPanel.title=Stavy zpracovaných objektů # SynchronizationInformationPanel.discoveryWarning=(The following numbers may include processing triggered by the discovery mechanism.) SynchronizationInformationPanel.unlinked=Odpojený SynchronizationInformationPanel.unmatched=Nenalezený -# ActionsExecutedInformationPanel.title=Actions executed +ActionsExecutedInformationPanel.title=Zpracované akce # ActionsExecutedInformationPanel.showingResultingActionsOnly=Showing "resulting actions" only. E.g. user ADD and MODIFY in one synchronization operation is shown as ADD. -# ActionsExecutedInformationPanel.showingAllActions=Showing all executed actions. -# ActionsExecutedInformationPanel.changeShowingActions=Change it. -# ActionsExecutedInformationPanel.objectType=Object type -# ActionsExecutedInformationPanel.operation=Operation -# ActionsExecutedInformationPanel.channel=Channel -# ActionsExecutedInformationPanel.successCount=Count (OK) -# ActionsExecutedInformationPanel.lastSuccessObject=Last (OK) -# ActionsExecutedInformationPanel.lastSuccessTimestamp=Time -# ActionsExecutedInformationPanel.failureCount=Count (failure) +ActionsExecutedInformationPanel.showingAllActions=Zobrazit všechny zpracované akce. +ActionsExecutedInformationPanel.changeShowingActions=Změnit. +ActionsExecutedInformationPanel.objectType=Typ objektu +ActionsExecutedInformationPanel.operation=Operace +ActionsExecutedInformationPanel.channel=Kanál +ActionsExecutedInformationPanel.successCount=Počet (OK) +ActionsExecutedInformationPanel.lastSuccessObject=Poslední (OK) +ActionsExecutedInformationPanel.lastSuccessTimestamp=Čas +ActionsExecutedInformationPanel.failureCount=Počet (selhání) SynchronizationPolicyDecision.ADD=Vložit SynchronizationPolicyDecision.DELETE=Smazat SynchronizationPolicyDecision.KEEP=Neměnit @@ -2560,13 +2560,13 @@ SystemConfigPanel.title.misc=Různé SystemConfigPanel.title.modelHooks=Model hooks SystemConfigPanel.title.notification=Notifikace SystemConfigPanel.title.passwordPolicy=Globální politika hesel -# SystemConfigPanel.title.securityPolicy=Global security policy +SystemConfigPanel.title.securityPolicy=Globální bezpečnostní politika SystemConfigPanel.title.userTemplate=Výhozí šablona uživatele SystemConfigPanel.tooltip.duration=Formát\: P[n][p], n-číslo, p-perioda (d - dny, m - měsíce, ...), P3M - vyčištění každé 3 měsíce -# SystemInfoPanel.cpuUsage=CPU Usage -# SystemInfoPanel.heapMemory=Heap memory (used/committed/max) -# SystemInfoPanel.nonHeapMemory=Non heap memory (used/committed/max) -# SystemInfoPanel.threads=Threads (live/peak/total) +SystemInfoPanel.cpuUsage=Využití CPU +SystemInfoPanel.heapMemory=Heap memory (used/committed/max) +SystemInfoPanel.nonHeapMemory=Non heap memory (used/committed/max) +SystemInfoPanel.threads=Vlákna (live/peak/total) TaskDtoExecutionStatus.CLOSED=Ukončený TaskDtoExecutionStatus.CLOSED.withTimestamp=Ukončený v ${} TaskDtoExecutionStatusFilter.ALL=Všechny stavy @@ -2589,7 +2589,7 @@ TaskListType.ACTIVATED=Aktivovaný TaskListType.ALL=Vše TaskListType.DEACTIVATED=Deaktivovaný TaskListType.EXECUTING=Spuštěný -# TaskStatePanel.countersSource=Statistical and state information source\: +TaskStatePanel.countersSource=Statistické informace a stav aplikace\: TaskStatePanel.currentObjectProcessed=Zpracovávaný objekt TaskStatePanel.executionStatus=Stav běhu TaskStatePanel.executionTime=Čas běhu @@ -2613,7 +2613,7 @@ TaskStatePanel.objectsProcessedSuccess=Objekty úspěšně zpracovány TaskStatePanel.objectsTotal=Celkem zpracováno objektů TaskStatePanel.opResult=Výsledek operace TaskStatePanel.progress=Zpracování -# TaskStatePanel.statistics=Environmental performance statistics +TaskStatePanel.statistics=Statistiky výkonu prostředí TaskStatePanel.subtaskName=Název TaskStatePanel.subtaskObjectsProcessed=Zpracovaných objektů TaskStatePanel.subtaskState=Stav @@ -2641,14 +2641,14 @@ ThreadStopActionType.CLOSE=Ukončit ThreadStopActionType.RESCHEDULE=Přeplánovat ThreadStopActionType.RESTART=Restartovat ThreadStopActionType.SUSPEND=Pozastavit -# ThreeStateBooleanPanel.false=False +ThreeStateBooleanPanel.false=Nepravda ThreeStateBooleanPanel.true=Pravda ThreeStateBooleanPanel.undef=Nedefinováno timeouts=Časové limity Title.CurrentStatus=Poslední stavová zpráva Title.MappingsStatistics=Informace o vyhodnocení mapování Title.NotificationsStatistics=Notifikační informace -# Title.ProvisioningStatistics=Provisioning operations information +Title.ProvisioningStatistics=Informace o provisioningu Title.Source=Zdroj\: TreeTablePanel.childOrg=Podřízené org. jednotky TreeTablePanel.collapseAll=Sbalit vše @@ -2672,25 +2672,25 @@ TreeTablePanel.menu.removeFromHierarchy=Odebrat z org. jednotky TreeTablePanel.message.deleteObjectConfirm=Opravdu chcete odebrat {0} zvolených objektů? TreeTablePanel.message.deleteRootConfirm=Opravdu chcete odebrat {0} ({1})? TreeTablePanel.message.nothingSelected=Nebyly vybrány žádné objekty. -# TreeTablePanel.message.recomputeError=Can't recompute Org. unit +TreeTablePanel.message.recomputeError=Nemohu přepočítat org. jednotku TreeTablePanel.moveRoot=Přesunout kořen TreeTablePanel.recomputeRoot=Přepočítat kořen TreeTablePanel.recomputeTask=Přepočítat uživatele v organizaci {0} -# TreeTablePanel.search.scope.one=One level -# TreeTablePanel.search.scope.subtree=Subtree +TreeTablePanel.search.scope.one=Jedaá úroveň +TreeTablePanel.search.scope.subtree=Podstrom Type.AUDIT=Audit type.nullValid=Vyberte jeden Type.RECONCILIATION=Rekonciliace -# typeSelect.null=All roles +typeSelect.null=Všechny role Type.USERS=Uživatel UploadPanel.delete.tooltip=Odebrat soubor UploadPanel.message.help=Vybrat soubor pro import. -# UploadPanel.message.removeError=File was not removed. +UploadPanel.message.removeError=Soubor byl odstraněn. UploadPanel.message.removeSuccess=Soubor byl odebrán. UploadPanel.message.uploadError=Nahrání souboru se nezdařilo. Zkuste to znovu. UploadPanel.message.uploadSuccess=Náhrání souboru proběhlo v pořádku. Pokračujte úpravami a stiskněte ULOŽIT až skončíte. UploadPanel.upload.tooltip=Nahrání souboru -# UploadPanel.download.tooltip=Download file +UploadPanel.download.tooltip=Stáhnout soubor userBrowserDialog.button.cancelButton=Zrušit userBrowserDialog.button.addButton=Vložit userBrowserDialog.button.searchButton=Hledat @@ -2703,16 +2703,16 @@ userBrowserDialog.name=Název userBrowserDialog.title=Vybrat uživatele userBrowserDialog.type=Typ User.disabled=Zakázaný -# UserMenuPanel.editPasswordQuestions=Security Questions +UserMenuPanel.editPasswordQuestions=Bezpečnostní otázky UserMenuPanel.editProfile=Upravit profil UserMenuPanel.logout=Odhlásit se -# UserMenuPanel.resetPasswords=Reset password -# UserOrgReferenceChoosePanel.type.org=Org. Unit +UserMenuPanel.resetPasswords=Reset hesla +UserOrgReferenceChoosePanel.type.org=Org. jednotka UserOrgReferenceChoosePanel.type=Typ vlastníka UserOrgReferenceChoosePanel.type.user=Uživatel UserReportConfigPanel.dateFrom=Od UserReportConfigPanel.dateTo=Do -# UserReportConfigPanel.exportFileType=Export Type +UserReportConfigPanel.exportFileType=Typ exportu UserReportConfigPanel.title.basic=Základní konfigurace reportů User.superuser=Superuživatel UserType.emailAddress=Email @@ -2720,7 +2720,7 @@ UserType.familyName=Příjmení UserType.fullName=Celé jméno UserType.givenName=Křestní validFromFetchStrategy.nullValid=Vyberte jeden -# validToFetchStrategy.nullValid=Choose One +validToFetchStrategy.nullValid=Vyberte jeden valueAttribute.nullValid=Vyberte jeden WebModelUtils.couldntLoadObject=Nemohu načíst objekt. web.security.provider.access.denied=Přístup odepřen. Nemáte právo přístupu, kontaktujte administrátory. @@ -2736,63 +2736,63 @@ WfDeltasPanel.label.deltaOutListEmpty=(prázdný) WfDeltasPanel.label.deltaOut=Výstup procesu\: Výsledky změn po schválení WfHistoryPanel.label.event=Událost WfHistoryPanel.label.timestamp=Čas -# WizardHelpDialog.button.ok=Ok, Got It\! +WizardHelpDialog.button.ok=Ok, hotovo\! WizardHelpDialog.label=Získat nápovědu pro Průvodce připojením aplikace\! -# Wizard.message.cancel=Resource editing was canceled +Wizard.message.cancel=Úpravy aplikace byly zrušeny WizardStep.title= WorkflowInformationPanel.label.history=Historie žádostí WorkflowInformationPanel.link.processInstance=Proces žádosti je ve stavu\: ${workflowLastDetails} WorkItemsPanel.assigned=Přiřazeno WorkItemsPanel.created=Vytvořeno WorkItemsPanel.name=Název -# PageAdmin.menu.dashboard=Dashboard -# PageAdmin.menu.selfDashboard=Home -# PageAdmin.menu.selfService=SELF SERVICE -# PageAdmin.menu.mainNavigation=ADMINISTRATION -# PageAdmin.menu.profile=Profile -# PageAdmin.menu.assignments=Assignments -# PageAdmin.menu.credentials=Credentials -# PageTemplate.version=Version\: -# PageTemplate.copy=Copyright © 2010-2015 Evolveum and partners. Thank you for using midPoint -# PageTemplate.toggleNavigation=Toggle navigation -# PageTemplate.user=user -# PageTemplate.couldntNavigateBreadcrumb=Couldn't navigate breadcrumb, reason\: {0} -# SystemInfoPanel.starttime=Start time -# SystemInfoPanel.uptime=Uptime -# CountToolbar.label.unknownCount=Displaying {0,number,integer} to {1,number,integer}, unknown number of matching results. -# TableConfigurationPanel.pageSize=Page size -# TableConfigurationPanel.tableColumns=Table columnsCountToolbar.label.unknownCount\=Displaying {0,number,integer} to {1,number,integer}, unknown number of matching results. -# MyRequestsPanel.started = Started -# MyRequestsPanel.rejected = Rejected -# MyRequestsPanel.approved = Approved -# MyRequestsPanel.name = Name -# PageSelfDashboard.title=Home -# PageSelfDashboard.workItems=My work items -# PageSelfDashboard.myRequests=My requests -# PageAdmin.menu.top.serverTasks.edit=Edit task -# PageAdmin.menu.top.configuration.repositoryObjectView=Edit object -# PageAdmin.menu.top.reports.configure=Configure report -# PageAdmin.menu.top.users.edit=Edit user -# PageAdmin.menu.top.roles.edit=Edit role -# PageAdmin.menu.top.users.org.edit=Edit organization -# PageSelfCredentials.tabs.password=Password -# PageSelfCredentials.title=Credentials -# PageSelfCredentials.oldPasswordLabel=Old password -# PageSelfCredentials.passwordLabel1=Password -# PageSelfCredentials.passwordLabel2=Confirm password -# PageSelfCredentials.accountMidpoint=MidPoint -# PageSelfCredentials.resourceMidpoint=MidPoint Repository -# PageSelfCredentials.noAccountSelected=Password not changed. No account was selected. -# PageSelfCredentials.incorrectOldPassword=Password not changed. Old password is incorrect. -# PageSelfCredentials.specifyOldPasswordMessage=Please, specify old password value -# ChangePasswordPanel.accountsTable.header=Password propagation -# ChangePasswordPanel.name=Name +PageAdmin.menu.dashboard=Nástěnka +PageAdmin.menu.selfDashboard=Domů +PageAdmin.menu.selfService=SAMOOBSLUHA +PageAdmin.menu.mainNavigation=ADMINISTRACE +PageAdmin.menu.profile=Profil +PageAdmin.menu.assignments=Přiřazení +PageAdmin.menu.credentials=Pověření +PageTemplate.version=Verze\: +PageTemplate.copy=Copyright © 2010-2015 Evolveum a partneři. Děkujeme, že používáte midPoint +PageTemplate.toggleNavigation=Přepnout navigaci +PageTemplate.user=uživatel +PageTemplate.couldntNavigateBreadcrumb=Nelze procházet navigaci, důvod\: {0} +SystemInfoPanel.starttime=Čas spuštění +SystemInfoPanel.uptime=Uptime +CountToolbar.label.unknownCount=Zobrazuji {0,number,integer} až {1,number,integer}, neznámý počet vyhovujících záznamů. +TableConfigurationPanel.pageSize=Velikost stránky +TableConfigurationPanel.tableColumns=Tabulka columnsCountToolbar.label.unknownCount\=Zobrazuji {0,number,integer} až {1,number,integer}, uneznámý počet odpovídajících výsledků. +MyRequestsPanel.started = Spuštěno +MyRequestsPanel.rejected = Odmítnuto +MyRequestsPanel.approved = Schváleno +MyRequestsPanel.name = Název +PageSelfDashboard.title=Domů +PageSelfDashboard.workItems=Moje úkoly +PageSelfDashboard.myRequests=Moje požadavky +PageAdmin.menu.top.serverTasks.edit=Upravit úlohu +PageAdmin.menu.top.configuration.repositoryObjectView=Upravit objekt +PageAdmin.menu.top.reports.configure=Konfigurovat report +PageAdmin.menu.top.users.edit=Upravit uživatele +PageAdmin.menu.top.roles.edit=Upravit roli +PageAdmin.menu.top.users.org.edit=Upravit organizaci +PageSelfCredentials.tabs.password=Heslo +PageSelfCredentials.title=Pověření +PageSelfCredentials.oldPasswordLabel=Staré heslo +PageSelfCredentials.passwordLabel1=Heslo +PageSelfCredentials.passwordLabel2=Potvrdit heslo +PageSelfCredentials.accountMidpoint=MidPoint +PageSelfCredentials.resourceMidpoint=MidPoint Repository +PageSelfCredentials.noAccountSelected=Heslo nebylo změněno. Nebyl vybrán žádný účet. +PageSelfCredentials.incorrectOldPassword=Heslo nebylo změněno. Staré heslo není správně. +PageSelfCredentials.specifyOldPasswordMessage=Zadejte staré heslo +ChangePasswordPanel.accountsTable.header=Propagace hesla +ChangePasswordPanel.name=Název ChangePasswordPanel.resourceName=Aplikace -# ChangePasswordPanel.enabled=Enabled -# ChangePasswordPanel.legendMessage.selected= - Password will be changed -# ChangePasswordPanel.legendMessage.propagated= - Password might to be changed (based on policies defined in resources definitions) -# ChangePasswordPanel.legendMessage.deselected= - Password will not be changed -# PageBase.button.tooltip.clearSearch=Clear -# mainForm.uploadTooLarge = Upload must be less than ${maxSize}. -# mainForm.uploadFailed = File failed to upload\: ${exception.localizedMessage}PageSelfCredentials.couldntResolve\=Couldn't resolve resource. -# PageSelfCredentials.couldntResolve=Couldn't resolve resource. +ChangePasswordPanel.enabled=Povoleno +ChangePasswordPanel.legendMessage.selected= - Heslo bude změněno +ChangePasswordPanel.legendMessage.propagated= - Heslo může být změněno (v závislosti na politikách nastavených v definici aplikace) +ChangePasswordPanel.legendMessage.deselected= - Heslo nebude změněno +PageBase.button.tooltip.clearSearch=Vyčistit +mainForm.uploadTooLarge = Nahrávaný soubor musí být menší než ${maxSize}. +mainForm.uploadFailed = Chyba při nahrávání souboru\: ${exception.localizedMessage}PageSelfCredentials.couldntResolve\=Nepodařilo se kontaktovat aplikaci. +PageSelfCredentials.couldntResolve=Nepodařilo se kontaktovat aplikaci. diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint_de_DE.properties b/gui/admin-gui/src/main/resources/localization/Midpoint_de_DE.properties index c1910cd98aa..56a6c1325ca 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint_de_DE.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint_de_DE.properties @@ -21,7 +21,7 @@ ACAttributePanel.required=Wird benötigt AccessCertificationCampaignStateType.CLOSED=Abgeschlossen AccessCertificationCampaignStateType.CREATED=Erzeugt AccessCertificationCampaignStateType.IN_REMEDIATION=In der Nachbesserung -# AccessCertificationCampaignStateType.IN_REVIEW_STAGE_FULL=In review stage {0} ({1}) +AccessCertificationCampaignStateType.IN_REVIEW_STAGE_FULL=Wird überprüft {0} {(1)} AccessCertificationCampaignStateType.IN_REVIEW_STAGE=Wird überprüft AccessCertificationCampaignStateType.REVIEW_STAGE_DONE_FULL=Überprüfung von {0} ({1}) abgeschlossen AccessCertificationCampaignStateType.REVIEW_STAGE_DONE=Überprüfung abgeschlossen @@ -55,9 +55,9 @@ assignablePopupContent.button.add=Hinzufügen assignablePopupContent.description=Beschreibung assignablePopupContent.displayName=Anzeigename # assignablePopupContent.message.errorLoadingRoleTypes=Could not load available role types for search purposes. -# assignablePopupContent.message.noOrgStructureDefined=No org. structure defined. +assignablePopupContent.message.noOrgStructureDefined=Keine Organisationsstruktur definiert assignablePopupContent.name=Name -# assignablePopupContent.role.type=Role type +assignablePopupContent.role.type=Rollentyp AssignmentEditorPanel.attributes=Attribute AssignmentEditorPanel.browser.title=Browser AssignmentEditorPanel.description=Beschreibung @@ -96,17 +96,17 @@ AssignmentPreviewDialog.type.direct=Direkt AssignmentPreviewDialog.type.indirect=Indirekt # AssignmentTablePanel.menu.assign=Assign Resource Account # AssignmentTablePanel.menu.assignOrg=Assign Org. -# AssignmentTablePanel.menu.assignRole=Assign Role -# AssignmentTablePanel.menu.unassign=Unassign +AssignmentTablePanel.menu.assignRole=Rolle zuweisen +AssignmentTablePanel.menu.unassign=Entziehen # AssignmentTablePanel.menu.showAllAssignments=Show all assignments # AssignmentTablePanel.message.couldntAssignObject=Couldn't assign object '{0}', reason\: {1}. # AssignmentTablePanel.message.illegalAssignmentState=Illegal assignment state '{0}'. # AssignmentTablePanel.message.noAssignmentSelected=No assignment selected. # AssignmentTablePanel.modal.message.delete=Do you really want to delete {0} assignment(s)? -# AssignmentTablePanel.modal.title.confirmDeletion=Confirm deletion +AssignmentTablePanel.modal.title.confirmDeletion=Löschung bestätigen # AssignmentTablePanel.modal.title.selectAssignment=Select object(s) AssignmentType.tenant=Besitzer -# AssignmentType.project=Org. unit/Project +AssignmentType.project=Organisationseinheit/Projekt associationAttribute.nullValid=Auswählen # AsyncDashboardPanel.loading=Loading data # AttributeFetchStrategyType.EXPLICIT=Explicit @@ -149,7 +149,7 @@ BeforeAfterType.AFTER=Nach BeforeAfterType.BEFORE=Vor Boolean.FALSE=Falsch Boolean.NULL=Undefiniert -# Boolean.TRUE=True +Boolean.TRUE=Wahr capabilityActivationPanel.label=Aktivierungskonfiguration capabilityActivationPanel.label.attributeName=Attributname capabilityActivationPanel.label.disableList=Liste sperren @@ -218,7 +218,7 @@ Channel.liveSync=Echtzeitsynchronisation Channel.null=Auswählen channel.nullValid=Auswählen Channel.reconciliation=Abgleich -Channel.user=Benutzer +Channel.user=Anwender Channel.webService=Web Service CheckTableHeader.label.error=Fehler CheckTableHeader.protected=Geschützt @@ -254,7 +254,7 @@ DebugButtonPanel.button.delete=Löschen DebugButtonPanel.button.export=Exportieren DecisionsPanel.comment=Kommentieren DecisionsPanel.result=Ergebnis -DecisionsPanel.user=Benutzer +DecisionsPanel.user=Anwender DecisionsPanel.when=Wann # deleteAllDialog.label.accountShadowsDelete=Account shadows to delete\: {0} # deleteAllDialog.label.nonAccountShadowsDelete=Non-Account shadows to delete\: {0} @@ -266,7 +266,7 @@ deleteAllDialog.label.org=Organisationseinheiten # deleteAllDialog.label.shadow.role=Role shadows # deleteAllDialog.label.totalToDelete=Total objects to delete\: {0} # deleteAllDialog.label.usersDelete=Users to delete\: {0} (User 'Administrator' will not be deleted) -# deleteAllDialog.label.users=Users +deleteAllDialog.label.users=Anwender # deleteAllDialog.message.choose=Choose object types to delete\: deleteAllDialog.no=Nein deleteAllDialog.yes=Ja @@ -362,19 +362,19 @@ H3Header.label.error=Fehler H3Header.showMore=Mehr Anzeigen HandlerUriActions.ACTION_ADD_ACCOUNT=Konto hinzufügen # HandlerUriActions.ACTION_ADD_FOCUS=Add focus -# HandlerUriActions.ACTION_ADD_USER=Add user +HandlerUriActions.ACTION_ADD_USER=Anwender hinzufügen # HandlerUriActions.ACTION_DELETE_ACCOUNT=Delete account # HandlerUriActions.ACTION_DELETE_FOCUS=Delete focus # HandlerUriActions.ACTION_DELETE_SHADOW=Delete shadow -# HandlerUriActions.ACTION_DELETE_USER=Delete user +HandlerUriActions.ACTION_DELETE_USER=Anwender entfernen # HandlerUriActions.ACTION_DISABLE_ACCOUNT=Disable account -# HandlerUriActions.ACTION_DISABLE_USER=Disable user +HandlerUriActions.ACTION_DISABLE_USER=Deaktiviere Anwender # HandlerUriActions.ACTION_INACTIVE_FOCUS=Inactive focus # HandlerUriActions.ACTION_INACTIVE_SHADOW=Inactive shadow # HandlerUriActions.ACTION_LINK_ACCOUNT=Link account # HandlerUriActions.ACTION_LINK=Link # HandlerUriActions.ACTION_MODIFY_PASSWORD=Modify password -# HandlerUriActions.ACTION_MODIFY_USER=Modify user +HandlerUriActions.ACTION_MODIFY_USER=Bearbeite Anwender # HandlerUriActions.ACTION_SYNCHRONIZE=Synchronize # HandlerUriActions.ACTION_UNLINK_ACCOUNT=Unlink account # HandlerUriActions.ACTION_UNLINK=Unlink @@ -580,7 +580,7 @@ MyAssignmentsPanel.assignment.displayName=Name # MyAssignmentsPanel.type.accountConstruction=Account construction MyAssignmentsPanel.type.error=Fehler # MyAssignmentsPanel.type.orgUnit=Org. unit -# MyAssignmentsPanel.type.role=Role +MyAssignmentsPanel.type.role=Rolle # NameStep.arrowToTurotialText=Each step of the wizard has a help button. Press this button to gain information about the purpose of a specific configuration step. # NameStep.connectorBundle=Bundle # NameStep.connectorHost=Connector host @@ -634,7 +634,7 @@ objectSyncConfig.editorKind.nullValid=Auswählen objectSyncConfig.editorObjectTemplate.nullValid=Auswählen objectTemplateRef.nullValid=Auswählen ObjectType.description=Beschreibung -# ObjectTypeGuiDescriptor.abstractRole=Abstract role +ObjectTypeGuiDescriptor.abstractRole=Abstrakte Rolle # ObjectTypeGuiDescriptor.accessCertificationCampaign=Access certification campaign # ObjectTypeGuiDescriptor.accessCertificationDefinition=Access certification definition # ObjectTypeGuiDescriptor.account=Account @@ -651,13 +651,13 @@ ObjectType.description=Beschreibung # ObjectTypeGuiDescriptor.reportOutput=Report output # ObjectTypeGuiDescriptor.report=Report ObjectTypeGuiDescriptor.resource=Ressource -# ObjectTypeGuiDescriptor.role=Role +ObjectTypeGuiDescriptor.role=Rolle # ObjectTypeGuiDescriptor.securityPolicy=Security policy # ObjectTypeGuiDescriptor.sequence=Sequence # ObjectTypeGuiDescriptor.shadow=Shadow # ObjectTypeGuiDescriptor.systemConfiguration=System configuration # ObjectTypeGuiDescriptor.task=Task -ObjectTypeGuiDescriptor.user=Benutzer +ObjectTypeGuiDescriptor.user=Anwender # ObjectTypeGuiDescriptor.valuePolicy=Value policy ObjectType.name=Name # ObjectType.parentOrgRef=Parent org. units @@ -694,7 +694,7 @@ ObjectType.name=Name # operation.com.evolveum.midpoint.model.controller.ModelControllerImpl.getSystemConfiguration=Get system configuration # operation.com.evolveum.midpoint.model.controller.ModelControllerImpl.processUserTemplate=Process user template # operation.com.evolveum.midpoint.model.controller.ModelControllerImpl.resolveAccountAttributes=Resolve account attributes -# operation.com.evolveum.midpoint.model.controller.ModelControllerImpl.resolveUserAttributes=Resolve user attributes +operation.com.evolveum.midpoint.model.controller.ModelControllerImpl.resolveUserAttributes=Löse Anwenderattribute auf # operation.com.evolveum.midpoint.model.controller.ModelControllerImpl.updateAccount=Update account # operation.com.evolveum.midpoint.model.controller.ModelController.modifyObjectWithExclusion=Modify object with exclusion # operation.com.evolveum.midpoint.model.controller.ModelController.processAddDeleteAccountFromChanges=Process account from changes @@ -705,7 +705,7 @@ ObjectType.name=Name # operation.com.evolveum.midpoint.model.controller.ModelDiagController.repositorySelfTest.user.searchObjects.employeeType=Search objects - employeeType (Model) # operation.com.evolveum.midpoint.model.controller.ModelDiagController.repositorySelfTest.user.searchObjects.fullName=Search objects - fullName (Model) # operation.com.evolveum.midpoint.model.controller.ModelDiagController.repositorySelfTest.user.searchObjects.organization=Search objects - organization (Model) -# operation.com.evolveum.midpoint.model.controller.SchemaHandler.insertUserDefinedVariables=Insert user defined variables +operation.com.evolveum.midpoint.model.controller.SchemaHandler.insertUserDefinedVariables=Füge anwenderdefinierte Variablen ein # operation.com.evolveum.midpoint.model.controller.SchemaHandler.processAttributeInbound=Process attribute inbound # operation.com.evolveum.midpoint.model.controller.SchemaHandler.processInboundHandling=Process inbound handling # operation.com.evolveum.midpoint.model.controller.SchemaHandler.processOutboundHandling=Process outbound handling @@ -821,10 +821,10 @@ ObjectType.name=Name # operation.com.evolveum.midpoint.web.page.admin.help.PageSystem.testRepository=Test repository (Gui) # operation.com.evolveum.midpoint.web.page.admin.home.PageDashboard.loadAccounts=Load accounts (Gui) # operation.com.evolveum.midpoint.web.page.admin.home.PageDashboard.loadAssignments=Load assignments (Gui) -# operation.com.evolveum.midpoint.web.page.admin.home.PageDashboard.loadUser=Load user (Gui) +operation.com.evolveum.midpoint.web.page.admin.home.PageDashboard.loadUser=Lade Anwender # operation.com.evolveum.midpoint.web.page.admin.home.PageDashboard.loadWorkItems=Load work items (Gui) # operation.com.evolveum.midpoint.web.page.admin.home.PageMyPasswords.loadAccount=Load account (Gui) -# operation.com.evolveum.midpoint.web.page.admin.home.PageMyPasswords.loadUser=Load user (Gui) +operation.com.evolveum.midpoint.web.page.admin.home.PageMyPasswords.loadUser=Lade Anwender # operation.com.evolveum.midpoint.web.page.admin.home.PageMyPasswords.loadUserWithAccounts=Load user with accounts (Gui) # operation.com.evolveum.midpoint.web.page.admin.home.PageMyPasswords.savePassword=Save password (Gui) # operation.com.evolveum.midpoint.web.page.admin.reports.PageReport.saveReport=Save report (Gui) @@ -844,9 +844,9 @@ ObjectType.name=Name # operation.com.evolveum.midpoint.web.page.admin.resources.PageResources.deleteResources=Delete resources (Gui) # operation.com.evolveum.midpoint.web.page.admin.resources.PageResources.syncStatus=Synchronization status (Gui) # operation.com.evolveum.midpoint.web.page.admin.resources.PageResources.testResource=Test resource (Gui) -# operation.com.evolveum.midpoint.web.page.admin.roles.PageRole.loadRole=Load role (Gui) -# operation.com.evolveum.midpoint.web.page.admin.roles.PageRole.saveRole=Save role (Gui) -# operation.com.evolveum.midpoint.web.page.admin.roles.PageRoles.deleteRoles=Delete roles (Gui) +operation.com.evolveum.midpoint.web.page.admin.roles.PageRole.loadRole=Lade Rolle (GUI) +operation.com.evolveum.midpoint.web.page.admin.roles.PageRole.saveRole=Speichere Rolle (GUI) +operation.com.evolveum.midpoint.web.page.admin.roles.PageRoles.deleteRoles=Lösche Rolle (GUI) # operation.com.evolveum.midpoint.web.page.admin.server.dto.NodeDtoProvider.countNodes=Count nodes (Gui) # operation.com.evolveum.midpoint.web.page.admin.server.dto.NodeDtoProvider.listNodes=List nodes (Gui) # operation.com.evolveum.midpoint.web.page.admin.server.dto.TaskDtoProvider.countTasks=Count tasks (Gui) @@ -875,19 +875,19 @@ ObjectType.name=Name # operation.com.evolveum.midpoint.web.page.admin.users.PageUser.loadAccounts=Load accounts (Gui) # operation.com.evolveum.midpoint.web.page.admin.users.PageUser.loadAssignment=Load assignment (Gui) # operation.com.evolveum.midpoint.web.page.admin.users.PageUser.loadAssignments=Load assignments (Gui) -# operation.com.evolveum.midpoint.web.page.admin.users.PageUser.loadUser=Load user (Gui) +operation.com.evolveum.midpoint.web.page.admin.users.PageUser.loadUser=Lade Anwender # operation.com.evolveum.midpoint.web.page.admin.users.PageUserPreview.modifyAccount=Modify account (Gui) # operation.com.evolveum.midpoint.web.page.admin.users.PageUserPreview.saveUser=Save user (Gui) # operation.com.evolveum.midpoint.web.page.admin.users.PageUser.save=Save user (Gui) # operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.deleteUser=Delete user (Gui) -# operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.deleteUsers=Delete users (Gui) +operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.deleteUsers=Lösche Anwender (GUI) # operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.disableUser=Disable user (Gui) -# operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.disableUsers=Disable users (Gui) +operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.disableUsers=Deaktiviere Anwender (GUI) # operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.enableUser=Enable user (Gui) -# operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.enableUsers=Enable users (Gui) +operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.enableUsers=Aktiviere Anwender (GUI) # operation.com.evolveum.midpoint.web.page.admin.users.PageUser.sendToSubmit=Send for submit (Gui) # operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.reconcileUser=Reconcile user (Gui)\: {0} -# operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.reconcileUsers=Reconcile users (Gui) +operation.com.evolveum.midpoint.web.page.admin.users.PageUsers.reconcileUsers=Anwender abgleichen (GUI) # operation.com.evolveum.midpoint.web.page.admin.workflow.PageWorkItem.saveWorkItem=Save work item (Gui) # operation.com.evolveum.midpoint.web.util.WebModelUtils.deleteObject=Delete object (Gui) # operation.com.evolveum.midpoint.web.util.WebModelUtils.loadObject=Load object (Gui) @@ -1079,18 +1079,18 @@ PageAdmin.menu.top.configuration.configuration=Konfiguration # PageAdmin.menu.top.resources.new=New resource # PageAdmin.menu.top.resources=Resources # PageAdmin.menu.top.roles.list=List roles -# PageAdmin.menu.top.roles.new=New role -# PageAdmin.menu.top.roles=Roles +PageAdmin.menu.top.roles.new=Neue Rolle +PageAdmin.menu.top.roles=Rollen # PageAdmin.menu.top.serverTasks.list=List tasks # PageAdmin.menu.top.serverTasks.new=New task # PageAdmin.menu.top.serverTasks=Server tasks -# PageAdmin.menu.top.users.find=Find users -# PageAdmin.menu.top.users.list=List users +PageAdmin.menu.top.users.find=Suche Anwender +PageAdmin.menu.top.users.list=Anwender auflisten # PageAdmin.menu.top.users.new=New user # PageAdmin.menu.top.users.org.new=New organization # PageAdmin.menu.top.users.org=Org. structure # PageAdmin.menu.top.users.org.tree=Organization tree -# PageAdmin.menu.top.users=Users +PageAdmin.menu.top.users=Anwender # PageAdmin.menu.top.workItems.listClaimable=Items claimable by me # PageAdmin.menu.top.workItems.list=My items # PageAdmin.menu.top.workItems.listProcessInstancesAll=All requests @@ -1101,8 +1101,8 @@ PageAdmin.menu.top.configuration.configuration=Konfiguration # pageAdmin.reports=Reports # pageAdminFocus.subTitle.editUserType=user '{0}' # pageAdminFocus.subTitle.newUserType=new user -# pageAdminFocus.subTitle.editRoleType=role '{0}' -# pageAdminFocus.subTitle.newRoleType=new role +pageAdminFocus.subTitle.editRoleType=Rolle '{0}' +pageAdminFocus.subTitle.newRoleType=Neue Rolle # pageAdminFocus.subTitle.editOrgType=organization '{0}' # pageAdminFocus.subTitle.newOrgType=new organization # pageAdminFocus.title.editFocusType=Edit @@ -1112,9 +1112,9 @@ PageAdmin.menu.top.configuration.configuration=Konfiguration # pageAdminFocus.message.noAssignmentsAvailable=There are currently no assignments to preview. # pageAdminFocus.message.noOrgSelected=No organization was selected. # pageAdminFocus.menu.assignShadow=Assign resource -# pageAdminFocus.menu.assignRole=Assign role +pageAdminFocus.menu.assignRole=Rolle zuweisen # pageAdminFocus.menu.assignOrg=Assign org. unit -# pageAdminFocus.menu.unassign=Unassign +pageAdminFocus.menu.unassign=Entziehen # pageAdminFocus.button.addShadow=Add projection # pageAdminFocus.button.enable=Enable # pageAdminFocus.button.disable=Disable @@ -1156,12 +1156,12 @@ pageAdminResources.contentAccounts=Konten # pageAdminResources.message.cantLoadResource=Couldn't load resource details. # pageAdminResources.newResource=New resource # pageAdmin.resources=Resources -# pageAdmin.roles.description=Roles configuration -# pageAdmin.roles=Roles +pageAdmin.roles.description=Rollen Konfiguration +pageAdmin.roles=Rollen # pageAdmin.serverTasks.description=Running tasks # pageAdmin.serverTasks=Server Tasks -# pageAdmin.users.description=Users in repository -# pageAdmin.users=Users +pageAdmin.users.description=Anwender im Repository +pageAdmin.users=Anwender # pageAdmin.workItems.description=Requests, approving # pageAdmin.workItems=Work Items # PageBase.button.abort=Abort @@ -1384,7 +1384,7 @@ pageCreatedReports.table.name=Name # PageCreatedReports.title=Created Reports # PageDashboard.accounts=My accounts # PageDashboard.activeTasks=Active Tasks -# PageDashboard.activeUsers=Active Users +PageDashboard.activeUsers=Aktive Anwender # PageDashboard.assignments=My Assignments # PageDashboard.personalInfo=Personal info # PageDashboard.serverLoad=Server Load @@ -1453,7 +1453,7 @@ pageDebugView.options=Optionen # PageError.quote=Failure is simply the opportunity to begin again, this time more intelligently. PageError.title=Fehler # PageFindUsers.subTitle=in midPoint -# PageFindUsers.title=Find users +PageFindUsers.title=Suche Anwender # PageForgetPassword.email=E-mail # pageForgetPassword.message.ContactAdminQuestionsNotSet=You have not set any security questions yet. Please Contact Your Administrator to reset Your Password. # pageForgetPassword.message.usernotfound=User Not Found @@ -1579,7 +1579,7 @@ PageMyPasswords.resourceName=Ressource # PageNewReport.message.nullFile=Uploaded file is null. # PageNewReport.subTitle=to midPoint # PageNewReport.title=Import Jasper report -# PageOrgTree.message.noOrgStructDefined=No org. structure defined. +PageOrgTree.message.noOrgStructDefined=Keine Organisationsstruktur definiert # PageOrgTree.subTitle=tree # PageOrgTree.title=Org. structure # pageOrgUnit.accounts=Projections @@ -1629,8 +1629,8 @@ PageReport.basic=Konfiguration # PageReports.report.auditName=Audit logs # PageReports.report.reconciliationDescription=Reconciliation report for selected resource. PageReports.report.reconciliationName=Abgleich -# PageReports.report.usersDescription=Users listed in MidPoint. -# PageReports.report.usersName=Users in MidPoint +PageReports.report.usersDescription=in MidPoint aufgeführte Anwender +PageReports.report.usersName=Anwender in MidPoint # PageReports.search.showSubreports=Show subreports # PageReports.subTitle=in midPoint PageReports.table.description=Beschreibung @@ -1729,9 +1729,9 @@ PageRoleEditor.label.name=Name # PageRoleEditor.message.cantCreateExtensionDelta=Can't create delta for role extension PageRoleEditor.subtitle.activation=Aktivierung # PageRoleEditor.subtitle.basic=Basic -# PageRoleEditor.subtitle.editingRole=role '{0}' +PageRoleEditor.subtitle.editingRole=Rolle '{0}' # PageRoleEditor.subtitle.extension=Extension -# PageRoleEditor.subtitle.newRole=new role +PageRoleEditor.subtitle.newRole=Neue Rolle PageRoleEditor.title.assignments=Zuweisungen # PageRoleEditor.title.editingRole=Edit PageRoleEditor.title.inducements=Veranlassungen @@ -1953,8 +1953,8 @@ pageUser.button.save=Speichern # pageUser.description=User in repository # pageUser.menu.assignAccount=Assign account # pageUser.menu.assignOrg=Assign org. unit -# pageUser.menu.assignRole=Assign role -# pageUser.menu.unassign=Unassign +pageUser.menu.assignRole=Rolle zuweisen +pageUser.menu.unassign=Entziehen # pageUser.message.cantCreateUser=Create user failed # pageUser.message.cantEditUser=Couldn't load form for editing user. # pageUser.message.cantNewUser=Couldn't load form for new user. @@ -1989,7 +1989,7 @@ pageUsers.menu.delete=Löschen # pageUsers.message.nothingSelected=No user has been selected. # pageUsers.message.queryError=Error occurred during translation search query to filter. # PageUsers.subTitle=in midPoint -# PageUsers.title=Users +PageUsers.title=Anwender # pageUser.subTitle.edituser=user '{0}' # pageUser.subTitle.newUser=new user # pageUser.task.category=Category @@ -2642,7 +2642,7 @@ TextField.universal.placeholder=Wert eintragen # ThreadStopActionType.RESTART=Restart # ThreadStopActionType.SUSPEND=Suspend ThreeStateBooleanPanel.false=Falsch -# ThreeStateBooleanPanel.true=True +ThreeStateBooleanPanel.true=Wahr # ThreeStateBooleanPanel.undef=Undef. # timeouts=Timeouts # Title.CurrentStatus=Last status message @@ -2675,13 +2675,13 @@ TreeTablePanel.menu.delete=Löschen # TreeTablePanel.message.recomputeError=Can't recompute Org. unit # TreeTablePanel.moveRoot=Move root # TreeTablePanel.recomputeRoot=Recompute root -# TreeTablePanel.recomputeTask=Recompute users in organization {0} +TreeTablePanel.recomputeTask=Anwender in Organisationen neu berechnen {0} # TreeTablePanel.search.scope.one=One level # TreeTablePanel.search.scope.subtree=Subtree # Type.AUDIT=Audit type.nullValid=Auswählen Type.RECONCILIATION=Abgleich -# typeSelect.null=All roles +typeSelect.null=Alle Rollen Type.USERS=Benutzer # UploadPanel.delete.tooltip=Remove file # UploadPanel.message.help=Choose file for import. @@ -2773,7 +2773,7 @@ MyRequestsPanel.name = Name # PageAdmin.menu.top.configuration.repositoryObjectView=Edit object # PageAdmin.menu.top.reports.configure=Configure report # PageAdmin.menu.top.users.edit=Edit user -# PageAdmin.menu.top.roles.edit=Edit role +PageAdmin.menu.top.roles.edit=Ändere Rolle # PageAdmin.menu.top.users.org.edit=Edit organization PageSelfCredentials.tabs.password=Passwort # PageSelfCredentials.title=Credentials From c84bb8d84696defd59265e15779b13d27f2d913e Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 11:11:23 +0100 Subject: [PATCH 048/116] Copying initial objects to config/ --- .../020-system-configuration.xml | 42 ++++++++++++++++ config/initial-objects/040-role-enduser.xml | 48 ++++++++++++++----- ...111-report-reconciliation-shadow-owner.xml | 13 ----- 3 files changed, 77 insertions(+), 26 deletions(-) delete mode 100644 config/initial-objects/111-report-reconciliation-shadow-owner.xml diff --git a/config/initial-objects/020-system-configuration.xml b/config/initial-objects/020-system-configuration.xml index d1ff93b95bc..8ce3eed242d 100644 --- a/config/initial-objects/020-system-configuration.xml +++ b/config/initial-objects/020-system-configuration.xml @@ -94,4 +94,46 @@ P1M + + + /self/profile + + View/edit your profile + + fa fa-user + + blue + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfProfile + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll + + + /self/credentials + + View/edit your credentials + + fa fa-shield + + red + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfCredentials + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll + + + /admin/users + + + fa fa-users + + green + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#users + + + /admin/resources + + + fa fa-building + + yellow + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#resources + + \ No newline at end of file diff --git a/config/initial-objects/040-role-enduser.xml b/config/initial-objects/040-role-enduser.xml index 6e85dd76052..5f89a4182be 100644 --- a/config/initial-objects/040-role-enduser.xml +++ b/config/initial-objects/040-role-enduser.xml @@ -19,8 +19,7 @@ End user Role authorizing end users to log in, change their passwords and review assigned accounts. - http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#dashboard - http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#myPasswords + http://midpoint.evolveum.com/xml/ns/public/security/authorization-ui-3#selfAll http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read @@ -38,19 +37,42 @@ - http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify - credentials + http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#changeCredentials + request + + self + + credentials - http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify - - ShadowType - - self - - - - credentials + http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#changeCredentials + request + + ShadowType + + self + + + credentials + + + http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify + execution + + self + + credentials + + + http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify + execution + + ShadowType + + self + + + credentials http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read diff --git a/config/initial-objects/111-report-reconciliation-shadow-owner.xml b/config/initial-objects/111-report-reconciliation-shadow-owner.xml deleted file mode 100644 index f8bd7ecf4f7..00000000000 --- a/config/initial-objects/111-report-reconciliation-shadow-owner.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - Shadow owner subreport - Shadow owner subreport for reconciliation report - false - - landscape - pdf - From 4d62014c358d8d20b67bf4a100f6adffb281e043 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 11:27:11 +0100 Subject: [PATCH 049/116] Release README-like files --- NEWS | 54 +++++++++++++++++++++++++++++---------------------- README | 2 +- RELEASE-NOTES | 2 +- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index 0a1f99ecf21..4413e171890 100644 --- a/NEWS +++ b/NEWS @@ -1,27 +1,35 @@ -midPoint 3.2 "Tycho" +midPoint 3.3 "Lincoln" ------------------------------- -Release 3.2 is a tenth midPoint release code-named Tycho. The Tycho release -brings new advanced LDAP connector, internal improvements and governance -technology preview. +Release 3.3 is a fifteenth midPoint release code-named Lincoln. The 3.3 +release brings major GUI look&feel improvements and miscellaneous new +features that improve practical usability of midPoint. -Release date: 5th August 2015 +Release date: 1st December 2015 -* Password recovery (security questions) -* Access certification (technology preview) -* referenceSearch expression to create a generic reference in expressions and mappings -* Reworked LDAP Connector -* LifeRay Portal connector -* Support for native attribute names -* Support for entitlement shortcut attributes (e.g. memberOf LDAP attribute) -* Support for auxiliary object classes -* Matching rule for LDAP distringuished name -* Support for synchronization of all object classes -* Asynchronous bulk delete task -* Improved logging of authorization processing -* Old values in audit deltas -* Improved audit log report -* Support "minimal" fetch strategy to avoid fetching of expensive attributes -* Support for recomputation of other than user objects -* GUI enhancements -* Minor improvements for international environments +Changes with respect to version 3.2: +* Significant GUI look&feel improvements +* New self-service GUI pages + End-user home page (end-user dashboard) + End-user profile page + End-user credentials change page +* Sequences +* Improvement of associationTargetSearch expression +* Aligned default value for user activation +* Aligned default value for allowEmptyValues in expressions +* LDAP-based connector for Active Directory (experimental) +* Run-time support for Java 8 environment +* Options for interpretation of expression empty values in queries +* Option to force legacy object class names in connectors +* Displaying role members on role details page +* Expanded audit record table for easier search in deltas +* Support for storing old values and object names in audit records +* Improved audit report +* Localization files switched to UTF-8 and single-file format +* Using transifex.com to support community localization +* Support for provisioning of user photo (jpeg binary data) +* Indirect role membership index (roleMembershipRef) +* Consistency mechanism improvements (self-healing) +* Improved reliability of strong mappings + +XPath2 scripting is deprecated and it is not supported in Java8 environment. diff --git a/README b/README index 19fa74b7c55..0dfc816462f 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -midPoint 3.2 "Tycho" +midPoint 3.3 "Lincoln" ------------------------------- General informations: diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 9e589bc7418..e50951afc57 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -1,4 +1,4 @@ To see actual releases notes please go to: -https://wiki.evolveum.com/display/midPoint/Release+3.2 +https://wiki.evolveum.com/display/midPoint/Release+3.3 From 219d671cdc99710153b9a74c553e70192a32524c Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 14:05:33 +0100 Subject: [PATCH 050/116] Version 3.3 (Lincoln) --- build-system/pom.xml | 4 +- cli/common/pom.xml | 4 +- cli/ninja/pom.xml | 4 +- cli/pom.xml | 4 +- cli/seppuku/pom.xml | 4 +- custom/pom.xml | 2 +- dist/midpoint-api/pom.xml | 10 ++-- dist/pom.xml | 8 +-- gui/admin-gui/pom.xml | 52 +++++++++---------- gui/pom.xml | 2 +- icf-connectors/dummy-connector-fake/pom.xml | 4 +- icf-connectors/dummy-connector/pom.xml | 6 +-- icf-connectors/dummy-resource/pom.xml | 6 +-- icf-connectors/pom.xml | 4 +- infra/common/pom.xml | 10 ++-- infra/pom.xml | 2 +- infra/prism-maven-plugin/pom.xml | 6 +-- infra/prism/pom.xml | 8 +-- .../main/resources/xml/ns/public/query-3.xsd | 2 +- .../main/resources/xml/ns/public/types-3.xsd | 2 +- infra/schema/pom.xml | 12 ++--- .../xml/ns/public/common/common-3.xsd | 2 +- infra/test-util/pom.xml | 6 +-- infra/util/pom.xml | 4 +- infra/ws-util/pom.xml | 4 +- model/certification-api/pom.xml | 10 ++-- model/certification-impl/pom.xml | 42 +++++++-------- model/model-api/pom.xml | 10 ++-- model/model-client/pom.xml | 10 ++-- model/model-common/pom.xml | 14 ++--- model/model-impl/pom.xml | 46 ++++++++-------- model/model-intest/pom.xml | 48 ++++++++--------- model/model-test/pom.xml | 38 +++++++------- model/notifications-api/pom.xml | 18 +++---- model/notifications-impl/pom.xml | 40 +++++++------- model/pom.xml | 2 +- model/report-api/pom.xml | 6 +-- model/report-impl/pom.xml | 38 +++++++------- model/workflow-api/pom.xml | 8 +-- model/workflow-impl/pom.xml | 44 ++++++++-------- pom.xml | 2 +- provisioning/pom.xml | 2 +- provisioning/provisioning-api/pom.xml | 8 +-- provisioning/provisioning-impl/pom.xml | 32 ++++++------ repo/audit-api/pom.xml | 8 +-- repo/audit-impl/pom.xml | 16 +++--- repo/pom.xml | 2 +- repo/repo-api/pom.xml | 8 +-- repo/repo-cache/pom.xml | 12 ++--- repo/repo-sql-impl-test/pom.xml | 8 +-- repo/repo-sql-impl/pom.xml | 10 ++-- repo/repo-test-util/pom.xml | 22 ++++---- repo/security-api/pom.xml | 6 +-- repo/security-impl/pom.xml | 16 +++--- repo/system-init/pom.xml | 14 ++--- repo/task-api/pom.xml | 6 +-- repo/task-quartz-impl/pom.xml | 22 ++++---- samples/model-client-sample/pom.xml | 2 +- samples/pom.xml | 2 +- samples/samples-test/pom.xml | 30 +++++------ testing/conntest/pom.xml | 30 +++++------ testing/consistency-mechanism/pom.xml | 30 +++++------ testing/longtest/pom.xml | 30 +++++------ testing/minipoint/pom.xml | 12 ++--- testing/pom.xml | 2 +- testing/rest/pom.xml | 32 ++++++------ testing/sanity/pom.xml | 42 +++++++-------- testing/selenidetest/pom.xml | 6 +-- testing/story/pom.xml | 30 +++++------ testing/wstest/pom.xml | 10 ++-- tools/gui-i18n/pom.xml | 4 +- tools/pom.xml | 2 +- tools/repo-ninja/pom.xml | 12 ++--- tools/schema-dist-maven-plugin/pom.xml | 6 +-- tools/test-ng/pom.xml | 2 +- tools/xjc-plugin/pom.xml | 8 +-- weblogic-build/pom.xml | 4 +- 77 files changed, 518 insertions(+), 518 deletions(-) diff --git a/build-system/pom.xml b/build-system/pom.xml index 9e5352ba7fe..c316fa865dd 100644 --- a/build-system/pom.xml +++ b/build-system/pom.xml @@ -25,7 +25,7 @@ com.evolveum.midpoint midpoint - 3.3-SNAPSHOT + 3.3 @@ -875,7 +875,7 @@ org.apache.directory.api api-all - 1.0.0-M32-SNAPSHOT + 1.0.0-M32-e1 slf4j-api diff --git a/cli/common/pom.xml b/cli/common/pom.xml index 9f602f1f48d..dc76475cd13 100644 --- a/cli/common/pom.xml +++ b/cli/common/pom.xml @@ -23,12 +23,12 @@ midPoint CLI Interface - common com.evolveum.midpoint.cli common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint cli - 3.3-SNAPSHOT + 3.3 diff --git a/cli/ninja/pom.xml b/cli/ninja/pom.xml index 0e573815ff2..8d9a575ff61 100644 --- a/cli/ninja/pom.xml +++ b/cli/ninja/pom.xml @@ -23,12 +23,12 @@ midPoint CLI Interface - ninja com.evolveum.midpoint.cli ninja - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint cli - 3.3-SNAPSHOT + 3.3 diff --git a/cli/pom.xml b/cli/pom.xml index f9e3ff959a8..7a611d26068 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -22,13 +22,13 @@ midPoint CLI Interface cli - 3.3-SNAPSHOT + 3.3 pom parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/cli/seppuku/pom.xml b/cli/seppuku/pom.xml index c92371c674c..ecf950189be 100644 --- a/cli/seppuku/pom.xml +++ b/cli/seppuku/pom.xml @@ -23,12 +23,12 @@ midPoint CLI Interface - seppuku com.evolveum.midpoint.cli seppuku - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint cli - 3.3-SNAPSHOT + 3.3 diff --git a/custom/pom.xml b/custom/pom.xml index f024e4a8011..86d421db29e 100644 --- a/custom/pom.xml +++ b/custom/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/dist/midpoint-api/pom.xml b/dist/midpoint-api/pom.xml index 6b95b5b7165..ccfa67d2e00 100644 --- a/dist/midpoint-api/pom.xml +++ b/dist/midpoint-api/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -51,22 +51,22 @@ com.evolveum.midpoint.model model-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra schema - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 diff --git a/dist/pom.xml b/dist/pom.xml index fdb1757f01e..f93b3dea4ac 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml @@ -51,20 +51,20 @@ com.evolveum.midpoint.gui admin-gui - 3.3-SNAPSHOT + 3.3 war com.evolveum.midpoint.tools repo-ninja - 3.3-SNAPSHOT + 3.3 zip bin com.evolveum.midpoint.tools repo-ninja - 3.3-SNAPSHOT + 3.3 org.testng diff --git a/gui/admin-gui/pom.xml b/gui/admin-gui/pom.xml index edef8da1670..96ee76a87ac 100644 --- a/gui/admin-gui/pom.xml +++ b/gui/admin-gui/pom.xml @@ -20,11 +20,11 @@ com.evolveum.midpoint.gui admin-gui war - 3.3-SNAPSHOT + 3.3 gui com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -213,7 +213,7 @@ com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 jaxb-impl @@ -228,38 +228,38 @@ com.evolveum.midpoint.model report-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model certification-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model workflow-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model notifications-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 runtime @@ -278,7 +278,7 @@ com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 runtime @@ -302,25 +302,25 @@ com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 runtime @@ -332,31 +332,31 @@ com.evolveum.midpoint.model certification-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.model workflow-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.model notifications-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 runtime com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 runtime @@ -368,7 +368,7 @@ com.evolveum.midpoint.model report-impl - 3.3-SNAPSHOT + 3.3 runtime @@ -381,7 +381,7 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 xml-apis @@ -491,13 +491,13 @@ com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl-test - 3.3-SNAPSHOT + 3.3 test @@ -514,7 +514,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -635,7 +635,7 @@ com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 test diff --git a/gui/pom.xml b/gui/pom.xml index 0fe2e46fe1d..0a3b8487bad 100644 --- a/gui/pom.xml +++ b/gui/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/icf-connectors/dummy-connector-fake/pom.xml b/icf-connectors/dummy-connector-fake/pom.xml index 58c415f9ff6..dd3c5a3fb93 100644 --- a/icf-connectors/dummy-connector-fake/pom.xml +++ b/icf-connectors/dummy-connector-fake/pom.xml @@ -20,12 +20,12 @@ Dummy Connector Fake com.evolveum.icf dummy-connector-fake - 3.3-SNAPSHOT + 3.3 jar icf-connectors com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git diff --git a/icf-connectors/dummy-connector/pom.xml b/icf-connectors/dummy-connector/pom.xml index afee1f17670..22bbef2b80f 100644 --- a/icf-connectors/dummy-connector/pom.xml +++ b/icf-connectors/dummy-connector/pom.xml @@ -20,12 +20,12 @@ Dummy Connector com.evolveum.icf dummy-connector - 3.3-SNAPSHOT + 3.3 jar icf-connectors com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -44,7 +44,7 @@ com.evolveum.icf dummy-resource - 3.3-SNAPSHOT + 3.3 org.testng diff --git a/icf-connectors/dummy-resource/pom.xml b/icf-connectors/dummy-resource/pom.xml index 0b5984feba1..96c60da74b8 100644 --- a/icf-connectors/dummy-resource/pom.xml +++ b/icf-connectors/dummy-resource/pom.xml @@ -20,12 +20,12 @@ Dummy Resource com.evolveum.icf dummy-resource - 3.3-SNAPSHOT + 3.3 jar icf-connectors com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 org.testng diff --git a/icf-connectors/pom.xml b/icf-connectors/pom.xml index b06490d7a49..ef312e4da84 100644 --- a/icf-connectors/pom.xml +++ b/icf-connectors/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml @@ -55,7 +55,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/infra/common/pom.xml b/infra/common/pom.xml index 8d16f231105..295b60f5459 100644 --- a/infra/common/pom.xml +++ b/infra/common/pom.xml @@ -24,7 +24,7 @@ infra com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,12 +35,12 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra schema - 3.3-SNAPSHOT + 3.3 commons-collections @@ -96,13 +96,13 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/infra/pom.xml b/infra/pom.xml index 9ddb2fd8f4d..fba0bb30241 100644 --- a/infra/pom.xml +++ b/infra/pom.xml @@ -22,7 +22,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/infra/prism-maven-plugin/pom.xml b/infra/prism-maven-plugin/pom.xml index 3dce75aef8e..78037017d8b 100644 --- a/infra/prism-maven-plugin/pom.xml +++ b/infra/prism-maven-plugin/pom.xml @@ -20,13 +20,13 @@ 4.0.0 com.evolveum.midpoint.infra prism-maven-plugin - 3.3-SNAPSHOT + 3.3 maven-plugin midPoint Infrastructure - prism maven plugin infra com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -49,7 +49,7 @@ com.evolveum.midpoint.infra prism - 3.3-SNAPSHOT + 3.3 commons-lang diff --git a/infra/prism/pom.xml b/infra/prism/pom.xml index 95dd1a07d8d..6a55fdb0837 100644 --- a/infra/prism/pom.xml +++ b/infra/prism/pom.xml @@ -20,12 +20,12 @@ 4.0.0 com.evolveum.midpoint.infra prism - 3.3-SNAPSHOT + 3.3 midPoint Infrastructure - prism infra com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test @@ -177,7 +177,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -193,7 +193,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/model/workflow-api/pom.xml b/model/workflow-api/pom.xml index 9628cef3613..6752681edf4 100644 --- a/model/workflow-api/pom.xml +++ b/model/workflow-api/pom.xml @@ -21,7 +21,7 @@ model com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 4.0.0 midPoint Workflow - api @@ -37,17 +37,17 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/model/workflow-impl/pom.xml b/model/workflow-impl/pom.xml index 219ce94adcc..99110abb79a 100644 --- a/model/workflow-impl/pom.xml +++ b/model/workflow-impl/pom.xml @@ -24,7 +24,7 @@ model com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,47 +35,47 @@ com.evolveum.midpoint.model workflow-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model notifications-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 org.activiti @@ -89,33 +89,33 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 provided com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 test-jar test com.evolveum.midpoint.model notifications-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.model report-api - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.model report-impl - 3.3-SNAPSHOT + 3.3 test @@ -126,7 +126,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -152,37 +152,37 @@ com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 test diff --git a/pom.xml b/pom.xml index 16990ca173f..0764fe03d40 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ midPoint Project com.evolveum.midpoint midpoint - 3.3-SNAPSHOT + 3.3 pom Utility module to compile all of the maven based midPoint projects. diff --git a/provisioning/pom.xml b/provisioning/pom.xml index 0d09962f4ab..f058d150563 100644 --- a/provisioning/pom.xml +++ b/provisioning/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/provisioning/provisioning-api/pom.xml b/provisioning/provisioning-api/pom.xml index 5375f53a6a3..a7adcb2c32f 100644 --- a/provisioning/provisioning-api/pom.xml +++ b/provisioning/provisioning-api/pom.xml @@ -20,12 +20,12 @@ midPoint Provisioning - api com.evolveum.midpoint.provisioning provisioning-api - 3.3-SNAPSHOT + 3.3 jar provisioning com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,12 +36,12 @@ com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/provisioning/provisioning-impl/pom.xml b/provisioning/provisioning-impl/pom.xml index 3bf4e457a6a..0a5e43daf79 100644 --- a/provisioning/provisioning-impl/pom.xml +++ b/provisioning/provisioning-impl/pom.xml @@ -24,7 +24,7 @@ provisioning com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,33 +35,33 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.provisioning provisioning-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 commons-pool @@ -89,7 +89,7 @@ com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 test @@ -100,19 +100,19 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 test @@ -123,13 +123,13 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test @@ -172,13 +172,13 @@ com.evolveum.icf dummy-connector - 3.3-SNAPSHOT + 3.3 test com.evolveum.icf dummy-resource - 3.3-SNAPSHOT + 3.3 test @@ -199,7 +199,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/audit-api/pom.xml b/repo/audit-api/pom.xml index 47bafb5379a..2eabce8adae 100644 --- a/repo/audit-api/pom.xml +++ b/repo/audit-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,18 +35,18 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 diff --git a/repo/audit-impl/pom.xml b/repo/audit-impl/pom.xml index 0dc046a6a19..59ee94a671e 100644 --- a/repo/audit-impl/pom.xml +++ b/repo/audit-impl/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,17 +35,17 @@ com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-api - 3.3-SNAPSHOT + 3.3 commons-pool @@ -60,7 +60,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -76,13 +76,13 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test @@ -93,7 +93,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/pom.xml b/repo/pom.xml index 392770a310d..be658c4cbee 100644 --- a/repo/pom.xml +++ b/repo/pom.xml @@ -22,7 +22,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/repo/repo-api/pom.xml b/repo/repo-api/pom.xml index d843f01746a..080392fc32c 100644 --- a/repo/repo-api/pom.xml +++ b/repo/repo-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,17 +35,17 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra schema - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/repo-cache/pom.xml b/repo/repo-cache/pom.xml index 337d111df7b..271e11dd82c 100644 --- a/repo/repo-cache/pom.xml +++ b/repo/repo-cache/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,22 +35,22 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra schema - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 @@ -61,7 +61,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/repo-sql-impl-test/pom.xml b/repo/repo-sql-impl-test/pom.xml index 820f6f24842..d2b570936bf 100644 --- a/repo/repo-sql-impl-test/pom.xml +++ b/repo/repo-sql-impl-test/pom.xml @@ -25,7 +25,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,12 +36,12 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 org.testng @@ -80,7 +80,7 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/repo-sql-impl/pom.xml b/repo/repo-sql-impl/pom.xml index 406e0be9ab7..f3b81d23ef8 100644 --- a/repo/repo-sql-impl/pom.xml +++ b/repo/repo-sql-impl/pom.xml @@ -25,7 +25,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,17 +36,17 @@ com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 @@ -96,7 +96,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/repo-test-util/pom.xml b/repo/repo-test-util/pom.xml index b9c11604105..b2a2ca486c5 100644 --- a/repo/repo-test-util/pom.xml +++ b/repo/repo-test-util/pom.xml @@ -23,7 +23,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -34,42 +34,42 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-sql-impl-test - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 org.testng @@ -78,12 +78,12 @@ com.evolveum.icf dummy-resource - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/security-api/pom.xml b/repo/security-api/pom.xml index 0cbc5cdddaf..b9e4c20cd5d 100644 --- a/repo/security-api/pom.xml +++ b/repo/security-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,12 +35,12 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/security-impl/pom.xml b/repo/security-impl/pom.xml index b01d37ddefd..14c00d8ea78 100644 --- a/repo/security-impl/pom.xml +++ b/repo/security-impl/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,17 +35,17 @@ com.evolveum.midpoint.repo security-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 @@ -56,7 +56,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -67,19 +67,19 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/system-init/pom.xml b/repo/system-init/pom.xml index e68ce340c41..c081ed68916 100644 --- a/repo/system-init/pom.xml +++ b/repo/system-init/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -47,22 +47,22 @@ com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 org.apache.cxf @@ -74,7 +74,7 @@ com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 @@ -86,7 +86,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/task-api/pom.xml b/repo/task-api/pom.xml index 072bbb5d603..8a64841082b 100644 --- a/repo/task-api/pom.xml +++ b/repo/task-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,12 +35,12 @@ com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/repo/task-quartz-impl/pom.xml b/repo/task-quartz-impl/pom.xml index 1cffdc89224..83df78d9e3b 100644 --- a/repo/task-quartz-impl/pom.xml +++ b/repo/task-quartz-impl/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -35,22 +35,22 @@ com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-cache - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-api - 3.3-SNAPSHOT + 3.3 commons-pool @@ -64,7 +64,7 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 provided @@ -76,7 +76,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -92,13 +92,13 @@ com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 test @@ -134,7 +134,7 @@ com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 test @@ -145,7 +145,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/samples/model-client-sample/pom.xml b/samples/model-client-sample/pom.xml index 34fbb4691f5..95cc4b4866f 100644 --- a/samples/model-client-sample/pom.xml +++ b/samples/model-client-sample/pom.xml @@ -144,7 +144,7 @@ com.evolveum.midpoint.model model-client - 3.3-SNAPSHOT + 3.3 org.apache.cxf diff --git a/samples/pom.xml b/samples/pom.xml index 93a5042d5be..8d385e87c16 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/samples/samples-test/pom.xml b/samples/samples-test/pom.xml index 578b73e004b..fce6c9c1186 100644 --- a/samples/samples-test/pom.xml +++ b/samples/samples-test/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 @@ -117,7 +117,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -139,13 +139,13 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test @@ -156,7 +156,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/conntest/pom.xml b/testing/conntest/pom.xml index ea664ba5cd7..c07c9bbbd40 100644 --- a/testing/conntest/pom.xml +++ b/testing/conntest/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 org.apache.directory.api @@ -121,7 +121,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -144,13 +144,13 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test @@ -161,7 +161,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/consistency-mechanism/pom.xml b/testing/consistency-mechanism/pom.xml index 00c02752cfc..a71fa3bcf2b 100644 --- a/testing/consistency-mechanism/pom.xml +++ b/testing/consistency-mechanism/pom.xml @@ -22,7 +22,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -59,47 +59,47 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 @@ -111,7 +111,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -133,19 +133,19 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 test @@ -156,7 +156,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/longtest/pom.xml b/testing/longtest/pom.xml index e9505ed951e..e001a3a2d0f 100644 --- a/testing/longtest/pom.xml +++ b/testing/longtest/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 @@ -117,7 +117,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -140,13 +140,13 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test @@ -157,7 +157,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/minipoint/pom.xml b/testing/minipoint/pom.xml index edcd1f09d0d..a141cf91a68 100644 --- a/testing/minipoint/pom.xml +++ b/testing/minipoint/pom.xml @@ -26,7 +26,7 @@ minipoint com.evolveum.midpoint.testing - 3.3-SNAPSHOT + 3.3 midPoint Testing - MiniPoint Atlassian JIRA @@ -38,7 +38,7 @@ https://fisheye.evolveum.com/browse/midPoint - 3.3-SNAPSHOT + 3.3 6.8.8 1.4.0.49 @@ -78,7 +78,7 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra @@ -137,7 +137,7 @@ com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.polygon @@ -152,12 +152,12 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 org.slf4j diff --git a/testing/pom.xml b/testing/pom.xml index 3bfda25bbea..0838961488a 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/testing/rest/pom.xml b/testing/rest/pom.xml index 32ea87c0882..e61d8a625e3 100644 --- a/testing/rest/pom.xml +++ b/testing/rest/pom.xml @@ -20,7 +20,7 @@ com.evolveum.midpoint parent - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml rest @@ -43,47 +43,47 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-api - 3.3-SNAPSHOT + 3.3 @@ -95,13 +95,13 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 test @@ -123,19 +123,19 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 test @@ -146,7 +146,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/sanity/pom.xml b/testing/sanity/pom.xml index 73e8ac151f6..f446c943401 100644 --- a/testing/sanity/pom.xml +++ b/testing/sanity/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -60,82 +60,82 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model report-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model report-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model notifications-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model notifications-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model workflow-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model workflow-impl - 3.3-SNAPSHOT + 3.3 @@ -147,7 +147,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -175,13 +175,13 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test @@ -192,7 +192,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/selenidetest/pom.xml b/testing/selenidetest/pom.xml index 5043b067631..49aa27286d8 100644 --- a/testing/selenidetest/pom.xml +++ b/testing/selenidetest/pom.xml @@ -6,12 +6,12 @@ Selenide tests com.evolveum.midpoint.testing selenidetest - 3.3-SNAPSHOT + 3.3 testing com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -57,7 +57,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/story/pom.xml b/testing/story/pom.xml index c16973f7626..1b09dfce835 100644 --- a/testing/story/pom.xml +++ b/testing/story/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.infra common - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-api - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.model model-test - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.provisioning provisioning-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo task-quartz-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo repo-test-util - 3.3-SNAPSHOT + 3.3 @@ -117,7 +117,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test @@ -145,13 +145,13 @@ com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 test @@ -162,7 +162,7 @@ com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 test diff --git a/testing/wstest/pom.xml b/testing/wstest/pom.xml index 04dd644a508..a7ba5580e80 100644 --- a/testing/wstest/pom.xml +++ b/testing/wstest/pom.xml @@ -22,7 +22,7 @@ com.evolveum.midpoint parent - 3.3-SNAPSHOT + 3.3 ../../build-system/pom.xml wstest @@ -42,7 +42,7 @@ com.evolveum.midpoint.model model-client - 3.3-SNAPSHOT + 3.3 org.apache.cxf @@ -73,13 +73,13 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.infra test-util - 3.3-SNAPSHOT + 3.3 test @@ -90,7 +90,7 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 test diff --git a/tools/gui-i18n/pom.xml b/tools/gui-i18n/pom.xml index 6d02d1cd9bf..b0a772e154d 100644 --- a/tools/gui-i18n/pom.xml +++ b/tools/gui-i18n/pom.xml @@ -25,7 +25,7 @@ tools com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -48,7 +48,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/tools/pom.xml b/tools/pom.xml index 9d2a86697a9..532fbe17f6f 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 ../build-system/pom.xml diff --git a/tools/repo-ninja/pom.xml b/tools/repo-ninja/pom.xml index 500132d6b39..2ec0aaf2803 100644 --- a/tools/repo-ninja/pom.xml +++ b/tools/repo-ninja/pom.xml @@ -25,7 +25,7 @@ tools com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,28 +36,28 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo system-init - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.repo security-impl - 3.3-SNAPSHOT + 3.3 com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test com.evolveum.midpoint.repo audit-impl - 3.3-SNAPSHOT + 3.3 diff --git a/tools/schema-dist-maven-plugin/pom.xml b/tools/schema-dist-maven-plugin/pom.xml index f2a6c355ada..e199d846dc6 100644 --- a/tools/schema-dist-maven-plugin/pom.xml +++ b/tools/schema-dist-maven-plugin/pom.xml @@ -20,13 +20,13 @@ 4.0.0 com.evolveum.midpoint.tools schema-dist-maven-plugin - 3.3-SNAPSHOT + 3.3 maven-plugin midPoint Tools - schema dist maven plugin tools com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -69,7 +69,7 @@ com.evolveum.midpoint.infra util - 3.3-SNAPSHOT + 3.3 diff --git a/tools/test-ng/pom.xml b/tools/test-ng/pom.xml index 54c761cf43f..8af314af305 100644 --- a/tools/test-ng/pom.xml +++ b/tools/test-ng/pom.xml @@ -24,7 +24,7 @@ tools com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git diff --git a/tools/xjc-plugin/pom.xml b/tools/xjc-plugin/pom.xml index 7df46ba5fd4..24d66a62b6c 100644 --- a/tools/xjc-plugin/pom.xml +++ b/tools/xjc-plugin/pom.xml @@ -19,13 +19,13 @@ 4.0.0 com.evolveum.midpoint.tools xjc-plugin - 3.3-SNAPSHOT + 3.3 jar midPoint Infrastructure - xjc plugin tools com.evolveum.midpoint - 3.3-SNAPSHOT + 3.3 https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.infra prism - 3.3-SNAPSHOT + 3.3 com.sun.xml.bind @@ -62,7 +62,7 @@ com.evolveum.midpoint.tools test-ng - 3.3-SNAPSHOT + 3.3 test diff --git a/weblogic-build/pom.xml b/weblogic-build/pom.xml index 5f9f38df407..b0758d95b41 100644 --- a/weblogic-build/pom.xml +++ b/weblogic-build/pom.xml @@ -20,7 +20,7 @@ com.evolveum.midpoint.dist midPoint-weblogic ear - 3.3-SNAPSHOT + 3.3 midPoint distribution for WebLogic Server https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.gui admin-gui - 3.3-SNAPSHOT + 3.3 war From 79b6c6fc832fde2ba86837cf5474ef8ec00a9f7e Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 1 Dec 2015 14:58:49 +0100 Subject: [PATCH 051/116] 3.4-SNAPSHOT development start --- build-system/pom.xml | 2 +- cli/common/pom.xml | 4 +- cli/ninja/pom.xml | 4 +- cli/pom.xml | 4 +- cli/seppuku/pom.xml | 4 +- custom/pom.xml | 2 +- dist/midpoint-api/pom.xml | 10 ++-- dist/pom.xml | 8 ++-- gui/admin-gui/pom.xml | 52 ++++++++++----------- gui/pom.xml | 2 +- icf-connectors/dummy-connector-fake/pom.xml | 4 +- icf-connectors/dummy-connector/pom.xml | 6 +-- icf-connectors/dummy-resource/pom.xml | 6 +-- icf-connectors/pom.xml | 4 +- infra/common/pom.xml | 10 ++-- infra/pom.xml | 2 +- infra/prism-maven-plugin/pom.xml | 6 +-- infra/prism/pom.xml | 8 ++-- infra/schema/pom.xml | 12 ++--- infra/test-util/pom.xml | 6 +-- infra/util/pom.xml | 4 +- infra/ws-util/pom.xml | 4 +- model/certification-api/pom.xml | 10 ++-- model/certification-impl/pom.xml | 42 ++++++++--------- model/model-api/pom.xml | 10 ++-- model/model-client/pom.xml | 10 ++-- model/model-common/pom.xml | 14 +++--- model/model-impl/pom.xml | 46 +++++++++--------- model/model-intest/pom.xml | 48 +++++++++---------- model/model-test/pom.xml | 38 +++++++-------- model/notifications-api/pom.xml | 18 +++---- model/notifications-impl/pom.xml | 40 ++++++++-------- model/pom.xml | 2 +- model/report-api/pom.xml | 6 +-- model/report-impl/pom.xml | 38 +++++++-------- model/workflow-api/pom.xml | 8 ++-- model/workflow-impl/pom.xml | 44 ++++++++--------- pom.xml | 2 +- provisioning/pom.xml | 2 +- provisioning/provisioning-api/pom.xml | 8 ++-- provisioning/provisioning-impl/pom.xml | 32 ++++++------- repo/audit-api/pom.xml | 8 ++-- repo/audit-impl/pom.xml | 16 +++---- repo/pom.xml | 2 +- repo/repo-api/pom.xml | 8 ++-- repo/repo-cache/pom.xml | 12 ++--- repo/repo-sql-impl-test/pom.xml | 8 ++-- repo/repo-sql-impl/pom.xml | 10 ++-- repo/repo-test-util/pom.xml | 22 ++++----- repo/security-api/pom.xml | 6 +-- repo/security-impl/pom.xml | 16 +++---- repo/system-init/pom.xml | 14 +++--- repo/task-api/pom.xml | 6 +-- repo/task-quartz-impl/pom.xml | 22 ++++----- samples/model-client-sample/pom.xml | 6 +-- samples/pom.xml | 2 +- samples/samples-test/pom.xml | 30 ++++++------ testing/conntest/pom.xml | 30 ++++++------ testing/consistency-mechanism/pom.xml | 30 ++++++------ testing/longtest/pom.xml | 30 ++++++------ testing/minipoint/pom.xml | 12 ++--- testing/pom.xml | 2 +- testing/rest/pom.xml | 32 ++++++------- testing/sanity/pom.xml | 42 ++++++++--------- testing/selenidetest/pom.xml | 6 +-- testing/story/pom.xml | 30 ++++++------ testing/wstest/pom.xml | 10 ++-- tools/gui-i18n/pom.xml | 4 +- tools/pom.xml | 2 +- tools/repo-ninja/pom.xml | 12 ++--- tools/schema-dist-maven-plugin/pom.xml | 6 +-- tools/test-ng/pom.xml | 2 +- tools/xjc-plugin/pom.xml | 8 ++-- weblogic-build/pom.xml | 4 +- 74 files changed, 516 insertions(+), 516 deletions(-) diff --git a/build-system/pom.xml b/build-system/pom.xml index c316fa865dd..5b3c8a47115 100644 --- a/build-system/pom.xml +++ b/build-system/pom.xml @@ -25,7 +25,7 @@ com.evolveum.midpoint midpoint - 3.3 + 3.4-SNAPSHOT diff --git a/cli/common/pom.xml b/cli/common/pom.xml index dc76475cd13..c9052c7dd51 100644 --- a/cli/common/pom.xml +++ b/cli/common/pom.xml @@ -23,12 +23,12 @@ midPoint CLI Interface - common com.evolveum.midpoint.cli common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint cli - 3.3 + 3.4-SNAPSHOT diff --git a/cli/ninja/pom.xml b/cli/ninja/pom.xml index 8d9a575ff61..65abd54ed80 100644 --- a/cli/ninja/pom.xml +++ b/cli/ninja/pom.xml @@ -23,12 +23,12 @@ midPoint CLI Interface - ninja com.evolveum.midpoint.cli ninja - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint cli - 3.3 + 3.4-SNAPSHOT diff --git a/cli/pom.xml b/cli/pom.xml index 7a611d26068..58ba6086fed 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -22,13 +22,13 @@ midPoint CLI Interface cli - 3.3 + 3.4-SNAPSHOT pom parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/cli/seppuku/pom.xml b/cli/seppuku/pom.xml index ecf950189be..d00c2b25684 100644 --- a/cli/seppuku/pom.xml +++ b/cli/seppuku/pom.xml @@ -23,12 +23,12 @@ midPoint CLI Interface - seppuku com.evolveum.midpoint.cli seppuku - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint cli - 3.3 + 3.4-SNAPSHOT diff --git a/custom/pom.xml b/custom/pom.xml index 86d421db29e..7ec33963026 100644 --- a/custom/pom.xml +++ b/custom/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/dist/midpoint-api/pom.xml b/dist/midpoint-api/pom.xml index ccfa67d2e00..1c993bdfce0 100644 --- a/dist/midpoint-api/pom.xml +++ b/dist/midpoint-api/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -51,22 +51,22 @@ com.evolveum.midpoint.model model-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra schema - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT diff --git a/dist/pom.xml b/dist/pom.xml index f93b3dea4ac..588bc4982a7 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml @@ -51,20 +51,20 @@ com.evolveum.midpoint.gui admin-gui - 3.3 + 3.4-SNAPSHOT war com.evolveum.midpoint.tools repo-ninja - 3.3 + 3.4-SNAPSHOT zip bin com.evolveum.midpoint.tools repo-ninja - 3.3 + 3.4-SNAPSHOT org.testng diff --git a/gui/admin-gui/pom.xml b/gui/admin-gui/pom.xml index 96ee76a87ac..500d4fbc607 100644 --- a/gui/admin-gui/pom.xml +++ b/gui/admin-gui/pom.xml @@ -20,11 +20,11 @@ com.evolveum.midpoint.gui admin-gui war - 3.3 + 3.4-SNAPSHOT gui com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -213,7 +213,7 @@ com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT jaxb-impl @@ -228,38 +228,38 @@ com.evolveum.midpoint.model report-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model certification-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model workflow-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model notifications-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT runtime @@ -278,7 +278,7 @@ com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT runtime @@ -302,25 +302,25 @@ com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT runtime @@ -332,31 +332,31 @@ com.evolveum.midpoint.model certification-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.model workflow-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.model notifications-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT runtime com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT runtime @@ -368,7 +368,7 @@ com.evolveum.midpoint.model report-impl - 3.3 + 3.4-SNAPSHOT runtime @@ -381,7 +381,7 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT xml-apis @@ -491,13 +491,13 @@ com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl-test - 3.3 + 3.4-SNAPSHOT test @@ -514,7 +514,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -635,7 +635,7 @@ com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT test diff --git a/gui/pom.xml b/gui/pom.xml index 0a3b8487bad..4495ebee3fa 100644 --- a/gui/pom.xml +++ b/gui/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/icf-connectors/dummy-connector-fake/pom.xml b/icf-connectors/dummy-connector-fake/pom.xml index dd3c5a3fb93..973448d0358 100644 --- a/icf-connectors/dummy-connector-fake/pom.xml +++ b/icf-connectors/dummy-connector-fake/pom.xml @@ -20,12 +20,12 @@ Dummy Connector Fake com.evolveum.icf dummy-connector-fake - 3.3 + 3.4-SNAPSHOT jar icf-connectors com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git diff --git a/icf-connectors/dummy-connector/pom.xml b/icf-connectors/dummy-connector/pom.xml index 22bbef2b80f..9fc770e2bc9 100644 --- a/icf-connectors/dummy-connector/pom.xml +++ b/icf-connectors/dummy-connector/pom.xml @@ -20,12 +20,12 @@ Dummy Connector com.evolveum.icf dummy-connector - 3.3 + 3.4-SNAPSHOT jar icf-connectors com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -44,7 +44,7 @@ com.evolveum.icf dummy-resource - 3.3 + 3.4-SNAPSHOT org.testng diff --git a/icf-connectors/dummy-resource/pom.xml b/icf-connectors/dummy-resource/pom.xml index 96c60da74b8..12c050154d3 100644 --- a/icf-connectors/dummy-resource/pom.xml +++ b/icf-connectors/dummy-resource/pom.xml @@ -20,12 +20,12 @@ Dummy Resource com.evolveum.icf dummy-resource - 3.3 + 3.4-SNAPSHOT jar icf-connectors com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT org.testng diff --git a/icf-connectors/pom.xml b/icf-connectors/pom.xml index ef312e4da84..7fe893a0b04 100644 --- a/icf-connectors/pom.xml +++ b/icf-connectors/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml @@ -55,7 +55,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/infra/common/pom.xml b/infra/common/pom.xml index 295b60f5459..b1bd9f2f105 100644 --- a/infra/common/pom.xml +++ b/infra/common/pom.xml @@ -24,7 +24,7 @@ infra com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,12 +35,12 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra schema - 3.3 + 3.4-SNAPSHOT commons-collections @@ -96,13 +96,13 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/infra/pom.xml b/infra/pom.xml index fba0bb30241..bee38483282 100644 --- a/infra/pom.xml +++ b/infra/pom.xml @@ -22,7 +22,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/infra/prism-maven-plugin/pom.xml b/infra/prism-maven-plugin/pom.xml index 78037017d8b..6e01857f54b 100644 --- a/infra/prism-maven-plugin/pom.xml +++ b/infra/prism-maven-plugin/pom.xml @@ -20,13 +20,13 @@ 4.0.0 com.evolveum.midpoint.infra prism-maven-plugin - 3.3 + 3.4-SNAPSHOT maven-plugin midPoint Infrastructure - prism maven plugin infra com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -49,7 +49,7 @@ com.evolveum.midpoint.infra prism - 3.3 + 3.4-SNAPSHOT commons-lang diff --git a/infra/prism/pom.xml b/infra/prism/pom.xml index 6a55fdb0837..1099649718c 100644 --- a/infra/prism/pom.xml +++ b/infra/prism/pom.xml @@ -20,12 +20,12 @@ 4.0.0 com.evolveum.midpoint.infra prism - 3.3 + 3.4-SNAPSHOT midPoint Infrastructure - prism infra com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test @@ -177,7 +177,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -193,7 +193,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/model/workflow-api/pom.xml b/model/workflow-api/pom.xml index 6752681edf4..c19ba086f67 100644 --- a/model/workflow-api/pom.xml +++ b/model/workflow-api/pom.xml @@ -21,7 +21,7 @@ model com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT 4.0.0 midPoint Workflow - api @@ -37,17 +37,17 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/model/workflow-impl/pom.xml b/model/workflow-impl/pom.xml index 99110abb79a..d9ba854ab2d 100644 --- a/model/workflow-impl/pom.xml +++ b/model/workflow-impl/pom.xml @@ -24,7 +24,7 @@ model com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,47 +35,47 @@ com.evolveum.midpoint.model workflow-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model notifications-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT org.activiti @@ -89,33 +89,33 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT provided com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT test-jar test com.evolveum.midpoint.model notifications-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.model report-api - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.model report-impl - 3.3 + 3.4-SNAPSHOT test @@ -126,7 +126,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -152,37 +152,37 @@ com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT test diff --git a/pom.xml b/pom.xml index 0764fe03d40..76b9775430c 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ midPoint Project com.evolveum.midpoint midpoint - 3.3 + 3.4-SNAPSHOT pom Utility module to compile all of the maven based midPoint projects. diff --git a/provisioning/pom.xml b/provisioning/pom.xml index f058d150563..b08f5a51efb 100644 --- a/provisioning/pom.xml +++ b/provisioning/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/provisioning/provisioning-api/pom.xml b/provisioning/provisioning-api/pom.xml index a7adcb2c32f..b26da351c3f 100644 --- a/provisioning/provisioning-api/pom.xml +++ b/provisioning/provisioning-api/pom.xml @@ -20,12 +20,12 @@ midPoint Provisioning - api com.evolveum.midpoint.provisioning provisioning-api - 3.3 + 3.4-SNAPSHOT jar provisioning com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,12 +36,12 @@ com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/provisioning/provisioning-impl/pom.xml b/provisioning/provisioning-impl/pom.xml index 0a5e43daf79..3067eed77aa 100644 --- a/provisioning/provisioning-impl/pom.xml +++ b/provisioning/provisioning-impl/pom.xml @@ -24,7 +24,7 @@ provisioning com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,33 +35,33 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.provisioning provisioning-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT commons-pool @@ -89,7 +89,7 @@ com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT test @@ -100,19 +100,19 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT test @@ -123,13 +123,13 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test @@ -172,13 +172,13 @@ com.evolveum.icf dummy-connector - 3.3 + 3.4-SNAPSHOT test com.evolveum.icf dummy-resource - 3.3 + 3.4-SNAPSHOT test @@ -199,7 +199,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/audit-api/pom.xml b/repo/audit-api/pom.xml index 2eabce8adae..3bf98f71cad 100644 --- a/repo/audit-api/pom.xml +++ b/repo/audit-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,18 +35,18 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT diff --git a/repo/audit-impl/pom.xml b/repo/audit-impl/pom.xml index 59ee94a671e..9f1cd9e7600 100644 --- a/repo/audit-impl/pom.xml +++ b/repo/audit-impl/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,17 +35,17 @@ com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-api - 3.3 + 3.4-SNAPSHOT commons-pool @@ -60,7 +60,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -76,13 +76,13 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test @@ -93,7 +93,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/pom.xml b/repo/pom.xml index be658c4cbee..1be64fe5746 100644 --- a/repo/pom.xml +++ b/repo/pom.xml @@ -22,7 +22,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/repo/repo-api/pom.xml b/repo/repo-api/pom.xml index 080392fc32c..c1b7e703416 100644 --- a/repo/repo-api/pom.xml +++ b/repo/repo-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,17 +35,17 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra schema - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/repo-cache/pom.xml b/repo/repo-cache/pom.xml index 271e11dd82c..5678976c31b 100644 --- a/repo/repo-cache/pom.xml +++ b/repo/repo-cache/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,22 +35,22 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra schema - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT @@ -61,7 +61,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/repo-sql-impl-test/pom.xml b/repo/repo-sql-impl-test/pom.xml index d2b570936bf..07586e69a43 100644 --- a/repo/repo-sql-impl-test/pom.xml +++ b/repo/repo-sql-impl-test/pom.xml @@ -25,7 +25,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,12 +36,12 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT org.testng @@ -80,7 +80,7 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/repo-sql-impl/pom.xml b/repo/repo-sql-impl/pom.xml index f3b81d23ef8..6166dbc5ba6 100644 --- a/repo/repo-sql-impl/pom.xml +++ b/repo/repo-sql-impl/pom.xml @@ -25,7 +25,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,17 +36,17 @@ com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT @@ -96,7 +96,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/repo-test-util/pom.xml b/repo/repo-test-util/pom.xml index b2a2ca486c5..50984ec6948 100644 --- a/repo/repo-test-util/pom.xml +++ b/repo/repo-test-util/pom.xml @@ -23,7 +23,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -34,42 +34,42 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-sql-impl-test - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT org.testng @@ -78,12 +78,12 @@ com.evolveum.icf dummy-resource - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/security-api/pom.xml b/repo/security-api/pom.xml index b9e4c20cd5d..719bca44370 100644 --- a/repo/security-api/pom.xml +++ b/repo/security-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,12 +35,12 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/security-impl/pom.xml b/repo/security-impl/pom.xml index 14c00d8ea78..814dc25d091 100644 --- a/repo/security-impl/pom.xml +++ b/repo/security-impl/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,17 +35,17 @@ com.evolveum.midpoint.repo security-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT @@ -56,7 +56,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -67,19 +67,19 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/system-init/pom.xml b/repo/system-init/pom.xml index c081ed68916..00ccede763f 100644 --- a/repo/system-init/pom.xml +++ b/repo/system-init/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -47,22 +47,22 @@ com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT org.apache.cxf @@ -74,7 +74,7 @@ com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT @@ -86,7 +86,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/task-api/pom.xml b/repo/task-api/pom.xml index 8a64841082b..ee779a5f8db 100644 --- a/repo/task-api/pom.xml +++ b/repo/task-api/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,12 +35,12 @@ com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/repo/task-quartz-impl/pom.xml b/repo/task-quartz-impl/pom.xml index 83df78d9e3b..126ed8393a2 100644 --- a/repo/task-quartz-impl/pom.xml +++ b/repo/task-quartz-impl/pom.xml @@ -24,7 +24,7 @@ repo com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -35,22 +35,22 @@ com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-cache - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-api - 3.3 + 3.4-SNAPSHOT commons-pool @@ -64,7 +64,7 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT provided @@ -76,7 +76,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -92,13 +92,13 @@ com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT test @@ -134,7 +134,7 @@ com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT test @@ -145,7 +145,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/samples/model-client-sample/pom.xml b/samples/model-client-sample/pom.xml index 95cc4b4866f..0e7af376c37 100644 --- a/samples/model-client-sample/pom.xml +++ b/samples/model-client-sample/pom.xml @@ -1,6 +1,6 @@ - 3.3-SNAPSHOT + 3.4-SNAPSHOT 1.7 @@ -144,7 +144,7 @@ com.evolveum.midpoint.model model-client - 3.3 + 3.4-SNAPSHOT org.apache.cxf diff --git a/samples/pom.xml b/samples/pom.xml index 8d385e87c16..47843741429 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/samples/samples-test/pom.xml b/samples/samples-test/pom.xml index fce6c9c1186..69f35065eb5 100644 --- a/samples/samples-test/pom.xml +++ b/samples/samples-test/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT @@ -117,7 +117,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -139,13 +139,13 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test @@ -156,7 +156,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/conntest/pom.xml b/testing/conntest/pom.xml index c07c9bbbd40..a066cf2688a 100644 --- a/testing/conntest/pom.xml +++ b/testing/conntest/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT org.apache.directory.api @@ -121,7 +121,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -144,13 +144,13 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test @@ -161,7 +161,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/consistency-mechanism/pom.xml b/testing/consistency-mechanism/pom.xml index a71fa3bcf2b..b1b95ba6a20 100644 --- a/testing/consistency-mechanism/pom.xml +++ b/testing/consistency-mechanism/pom.xml @@ -22,7 +22,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -59,47 +59,47 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT @@ -111,7 +111,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -133,19 +133,19 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT test @@ -156,7 +156,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/longtest/pom.xml b/testing/longtest/pom.xml index e001a3a2d0f..5a3ba5427ef 100644 --- a/testing/longtest/pom.xml +++ b/testing/longtest/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT @@ -117,7 +117,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -140,13 +140,13 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test @@ -157,7 +157,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/minipoint/pom.xml b/testing/minipoint/pom.xml index a141cf91a68..65b128d9a58 100644 --- a/testing/minipoint/pom.xml +++ b/testing/minipoint/pom.xml @@ -26,7 +26,7 @@ minipoint com.evolveum.midpoint.testing - 3.3 + 3.4-SNAPSHOT midPoint Testing - MiniPoint Atlassian JIRA @@ -38,7 +38,7 @@ https://fisheye.evolveum.com/browse/midPoint - 3.3 + 3.4-SNAPSHOT 6.8.8 1.4.0.49 @@ -78,7 +78,7 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra @@ -137,7 +137,7 @@ com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.polygon @@ -152,12 +152,12 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT org.slf4j diff --git a/testing/pom.xml b/testing/pom.xml index 0838961488a..aed3e66c46f 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/testing/rest/pom.xml b/testing/rest/pom.xml index e61d8a625e3..db686449785 100644 --- a/testing/rest/pom.xml +++ b/testing/rest/pom.xml @@ -20,7 +20,7 @@ com.evolveum.midpoint parent - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml rest @@ -43,47 +43,47 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-api - 3.3 + 3.4-SNAPSHOT @@ -95,13 +95,13 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT test @@ -123,19 +123,19 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT test @@ -146,7 +146,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/sanity/pom.xml b/testing/sanity/pom.xml index f446c943401..b94bc9216f7 100644 --- a/testing/sanity/pom.xml +++ b/testing/sanity/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -60,82 +60,82 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model report-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model report-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model notifications-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model notifications-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model workflow-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model workflow-impl - 3.3 + 3.4-SNAPSHOT @@ -147,7 +147,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -175,13 +175,13 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test @@ -192,7 +192,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/selenidetest/pom.xml b/testing/selenidetest/pom.xml index 49aa27286d8..a96994707fc 100644 --- a/testing/selenidetest/pom.xml +++ b/testing/selenidetest/pom.xml @@ -6,12 +6,12 @@ Selenide tests com.evolveum.midpoint.testing selenidetest - 3.3 + 3.4-SNAPSHOT testing com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -57,7 +57,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/story/pom.xml b/testing/story/pom.xml index 1b09dfce835..79abb427ef3 100644 --- a/testing/story/pom.xml +++ b/testing/story/pom.xml @@ -23,7 +23,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml @@ -60,52 +60,52 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.infra common - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-api - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.model model-test - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.provisioning provisioning-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo task-quartz-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo repo-test-util - 3.3 + 3.4-SNAPSHOT @@ -117,7 +117,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test @@ -145,13 +145,13 @@ com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT test @@ -162,7 +162,7 @@ com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT test diff --git a/testing/wstest/pom.xml b/testing/wstest/pom.xml index a7ba5580e80..3503dfb8355 100644 --- a/testing/wstest/pom.xml +++ b/testing/wstest/pom.xml @@ -22,7 +22,7 @@ com.evolveum.midpoint parent - 3.3 + 3.4-SNAPSHOT ../../build-system/pom.xml wstest @@ -42,7 +42,7 @@ com.evolveum.midpoint.model model-client - 3.3 + 3.4-SNAPSHOT org.apache.cxf @@ -73,13 +73,13 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.infra test-util - 3.3 + 3.4-SNAPSHOT test @@ -90,7 +90,7 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT test diff --git a/tools/gui-i18n/pom.xml b/tools/gui-i18n/pom.xml index b0a772e154d..14b25de0ada 100644 --- a/tools/gui-i18n/pom.xml +++ b/tools/gui-i18n/pom.xml @@ -25,7 +25,7 @@ tools com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -48,7 +48,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/tools/pom.xml b/tools/pom.xml index 532fbe17f6f..23e34c84c32 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -24,7 +24,7 @@ parent com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT ../build-system/pom.xml diff --git a/tools/repo-ninja/pom.xml b/tools/repo-ninja/pom.xml index 2ec0aaf2803..2b02fdc541c 100644 --- a/tools/repo-ninja/pom.xml +++ b/tools/repo-ninja/pom.xml @@ -25,7 +25,7 @@ tools com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,28 +36,28 @@ com.evolveum.midpoint.repo repo-sql-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo system-init - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.repo security-impl - 3.3 + 3.4-SNAPSHOT com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test com.evolveum.midpoint.repo audit-impl - 3.3 + 3.4-SNAPSHOT diff --git a/tools/schema-dist-maven-plugin/pom.xml b/tools/schema-dist-maven-plugin/pom.xml index e199d846dc6..50da811d130 100644 --- a/tools/schema-dist-maven-plugin/pom.xml +++ b/tools/schema-dist-maven-plugin/pom.xml @@ -20,13 +20,13 @@ 4.0.0 com.evolveum.midpoint.tools schema-dist-maven-plugin - 3.3 + 3.4-SNAPSHOT maven-plugin midPoint Tools - schema dist maven plugin tools com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -69,7 +69,7 @@ com.evolveum.midpoint.infra util - 3.3 + 3.4-SNAPSHOT diff --git a/tools/test-ng/pom.xml b/tools/test-ng/pom.xml index 8af314af305..e37b3239ac2 100644 --- a/tools/test-ng/pom.xml +++ b/tools/test-ng/pom.xml @@ -24,7 +24,7 @@ tools com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git diff --git a/tools/xjc-plugin/pom.xml b/tools/xjc-plugin/pom.xml index 24d66a62b6c..7d29548c1da 100644 --- a/tools/xjc-plugin/pom.xml +++ b/tools/xjc-plugin/pom.xml @@ -19,13 +19,13 @@ 4.0.0 com.evolveum.midpoint.tools xjc-plugin - 3.3 + 3.4-SNAPSHOT jar midPoint Infrastructure - xjc plugin tools com.evolveum.midpoint - 3.3 + 3.4-SNAPSHOT https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.infra prism - 3.3 + 3.4-SNAPSHOT com.sun.xml.bind @@ -62,7 +62,7 @@ com.evolveum.midpoint.tools test-ng - 3.3 + 3.4-SNAPSHOT test diff --git a/weblogic-build/pom.xml b/weblogic-build/pom.xml index b0758d95b41..31bbde1daac 100644 --- a/weblogic-build/pom.xml +++ b/weblogic-build/pom.xml @@ -20,7 +20,7 @@ com.evolveum.midpoint.dist midPoint-weblogic ear - 3.3 + 3.4-SNAPSHOT midPoint distribution for WebLogic Server https://github.com/Evolveum/midpoint.git @@ -36,7 +36,7 @@ com.evolveum.midpoint.gui admin-gui - 3.3 + 3.4-SNAPSHOT war From 4a83bc459f447051a13102c9e62bdd69cc3a8b32 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 1 Dec 2015 19:06:22 +0100 Subject: [PATCH 052/116] Preliminary support for Equal(path1, path2) predicate. Fixed ordering of cases on cert campaign page. --- .../admin/certification/PageCertCampaign.java | 3 + .../certification/PageCertCampaigns.java | 2 + .../midpoint/prism/query/EqualFilter.java | 15 +- .../midpoint/prism/query/ExistsFilter.java | 4 +- .../prism/query/PropertyValueFilter.java | 12 +- .../repo/sql/QueryInterpreter2Test.java | 172 +++++++++++++++- .../common/RAccessCertificationCampaign.java | 10 +- .../container/RAccessCertificationCase.java | 6 +- .../sql/helpers/CertificationCaseHelper.java | 4 +- .../sql/query2/InterpretationContext.java | 6 +- .../sql/query2/ItemPathResolutionState.java | 189 ++++++++++++++++++ ...reterHelper.java => ItemPathResolver.java} | 114 ++++------- .../repo/sql/query2/QueryInterpreter2.java | 19 +- .../sql/query2/hqm/RootHibernateQuery.java | 4 + .../PropertyPropertyComparisonCondition.java | 57 ++++++ .../restriction/AnyPropertyRestriction.java | 28 ++- .../query2/restriction/ExistsRestriction.java | 36 ++-- .../query2/restriction/ItemRestriction.java | 38 +++- .../restriction/ItemValueRestriction.java | 27 +-- .../restriction/PropertyRestriction.java | 46 ++++- .../restriction/ReferenceRestriction.java | 3 +- .../sql/query2/restriction/Restriction.java | 21 +- 22 files changed, 658 insertions(+), 158 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{InterpreterHelper.java => ItemPathResolver.java} (62%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java index 83f317ee62c..e0ce774ec27 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java @@ -43,10 +43,12 @@ import com.evolveum.midpoint.web.util.WebModelUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCasesStatisticsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; import org.apache.wicket.markup.html.basic.Label; @@ -253,6 +255,7 @@ private void initTableLayout(Form mainForm) { CertCaseDtoProvider provider = new CertCaseDtoProvider(PageCertCampaign.this); provider.setQuery(createCaseQuery()); provider.setCampaignOid(getCampaignOid()); + provider.setSort(AccessCertificationCaseType.F_OBJECT_REF.getLocalPart(), SortOrder.ASCENDING); // default sorting BoxedTablePanel table = new BoxedTablePanel<>(ID_DECISIONS_TABLE, provider, initColumns()); table.setShowPaging(true); table.setOutputMarkupId(true); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java index 05dfa796adc..9d4a67c0775 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java @@ -57,12 +57,14 @@ import com.evolveum.midpoint.web.util.WebModelUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; import org.apache.wicket.markup.html.form.Form; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java index 1a45e34c2e7..b8e8e238490 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java @@ -52,6 +52,10 @@ public class EqualFilter extends PropertyValueFilter definition, QName matchingRule, ItemPath rightSidePath) { + super(parentPath, definition, matchingRule, rightSidePath); + } + private EqualFilter(ItemPath parentPath, PrismPropertyDefinition definition, QName matchingRule) { super(parentPath, definition, matchingRule); } @@ -146,12 +150,17 @@ public static EqualFilter createEqual(ItemPath p return createEqual(propertyPath, type, prismContext, null, realValue); } - public static EqualFilter createEqual(ItemPath propertyPath, Class type, PrismContext prismContext, QName matchingRule, T realValue) - { + public static EqualFilter createEqual(ItemPath propertyPath, Class type, PrismContext prismContext, QName matchingRule, T realValue) { PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(propertyPath, type, prismContext); return createEqual(propertyPath, propertyDefinition, matchingRule, realValue); } - + + public static EqualFilter createEqual(ItemPath propertyPath, Class type, PrismContext prismContext, QName matchingRule, ItemPath rightSidePath) { + PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(propertyPath, type, prismContext); + EqualFilter filter = new EqualFilter(propertyPath, propertyDefinition, matchingRule, rightSidePath); + return filter; + } + public static EqualFilter createNullEqual(ItemPath itemPath, PrismPropertyDefinition propertyDef, QName matchingRule){ return new EqualFilter(itemPath, propertyDef, matchingRule); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java index fed5b14496c..ab01d06bbee 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java @@ -61,13 +61,13 @@ public ObjectFilter getFilter() { return filter; } - public static ExistsFilter createEquals(ItemPath itemPath, PrismContainerDefinition containerDef, + public static ExistsFilter createExists(ItemPath itemPath, PrismContainerDefinition containerDef, ObjectFilter filter) throws SchemaException { ItemDefinition itemDefinition = FilterUtils.findItemDefinition(itemPath, containerDef); return new ExistsFilter(itemPath, itemDefinition, filter); } - public static ExistsFilter createEquals(ItemPath itemPath, Class clazz, PrismContext prismContext, + public static ExistsFilter createExists(ItemPath itemPath, Class clazz, PrismContext prismContext, ObjectFilter filter) throws SchemaException { ItemDefinition itemDefinition = FilterUtils.findItemDefinition(itemPath, clazz, prismContext); return new ExistsFilter(itemPath, itemDefinition, filter); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java index 561b52a3452..42d7eb92243 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java @@ -57,10 +57,16 @@ public abstract class PropertyValueFilter extends ValueFil private ExpressionWrapper expression; private List values; + private ItemPath rightSidePath; PropertyValueFilter() { super(); } + + PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, ItemPath rightSidePath) { + super(path, definition, matchingRule); + this.rightSidePath = rightSidePath; + } PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, List values) { super(path, definition, matchingRule); @@ -190,7 +196,11 @@ public Item getFilterItem() throws SchemaException{ return filterItem; } - + + public ItemPath getRightSidePath() { + return rightSidePath; + } + public ExpressionWrapper getExpression() { return expression; } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 8adfd9518e4..9bf1637ace2 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule; import com.evolveum.midpoint.prism.match.PolyStringOrigMatchingRule; @@ -37,13 +38,11 @@ import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.OrFilter; -import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.prism.query.OrgFilter; import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.TypeFilter; -import com.evolveum.midpoint.prism.schema.PrismSchema; import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; @@ -65,6 +64,8 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; @@ -633,7 +634,7 @@ public void test080QueryExistsAssignment() throws Exception { /* * ### UserType: Exists (assignment, Equal (activation/administrativeStatus = Enabled)) */ - ExistsFilter filter = ExistsFilter.createEquals(new ItemPath(UserType.F_ASSIGNMENT), UserType.class, prismContext, + ExistsFilter filter = ExistsFilter.createExists(new ItemPath(UserType.F_ASSIGNMENT), UserType.class, prismContext, EqualFilter.createEqual(new ItemPath(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), AssignmentType.class, prismContext, null, ActivationStatusType.ENABLED)); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -1398,7 +1399,7 @@ public void test405ActivationQueryCorrect() throws Exception { thisScanTimestamp, true), LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true), - ExistsFilter.createEquals(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, + ExistsFilter.createExists(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, OrFilter.createOr( LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), assignmentDef, thisScanTimestamp, true), @@ -1543,7 +1544,7 @@ public void test415ActivationQueryCorrect() throws Exception { thisScanTimestamp, true) ), AndFilter.createAnd( - ExistsFilter.createEquals(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, + ExistsFilter.createExists(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, OrFilter.createOr( AndFilter.createAnd( GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), @@ -2709,6 +2710,167 @@ public void test820OrderByTargetName() throws Exception { } } + @Test(expectedExceptions = Exception.class) // should fail, as Equals supports single-value right side only + public void test900EqualsMultivalue() throws Exception { + Session session = open(); + + try { + /* + * ### User: preferredLanguage = 'SK', 'HU' + */ + PrismObjectDefinition userDef = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(UserType.class); + PrismPropertyDefinition prefLangDef = userDef.findPropertyDefinition(UserType.F_PREFERRED_LANGUAGE); + + PrismPropertyDefinition multivalDef = new PrismPropertyDefinition(UserType.F_PREFERRED_LANGUAGE, + DOMUtil.XSD_STRING, prismContext); + multivalDef.setMaxOccurs(-1); + PrismProperty multivalProperty = multivalDef.instantiate(); + multivalProperty.addRealValue("SK"); + multivalProperty.addRealValue("HU"); + + ObjectQuery query = ObjectQuery.createObjectQuery( + EqualFilter.createEqual(new ItemPath(UserType.F_PREFERRED_LANGUAGE), multivalProperty)); + + String real = getInterpretedQuery2(session, UserType.class, query); +// assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test910PreferredLanguageEqualsCostCenter() throws Exception { + Session session = open(); + + try { + /* + * ### User: preferredLanguage = costCenter + */ + ObjectQuery query = ObjectQuery.createObjectQuery( + EqualFilter.createEqual( + new ItemPath(UserType.F_PREFERRED_LANGUAGE), + UserType.class, + prismContext, + null, + new ItemPath(UserType.F_COST_CENTER))); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.fullObject,\n" + + " u.stringsCount,\n" + + " u.longsCount,\n" + + " u.datesCount,\n" + + " u.referencesCount,\n" + + " u.polysCount,\n" + + " u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " (\n" + + " u.preferredLanguage = u.costCenter or\n" + + " (\n" + + " u.preferredLanguage is null and\n" + + " u.costCenter is null\n" + + " )\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test915OrganizationEqualsCostCenter() throws Exception { + Session session = open(); + + try { + /* + * ### User: organization = costCenter + */ + ObjectQuery query = ObjectQuery.createObjectQuery( + EqualFilter.createEqual( + new ItemPath(UserType.F_ORGANIZATION), + UserType.class, + prismContext, + null, + new ItemPath(UserType.F_COST_CENTER))); + + String real = getInterpretedQuery2(session, UserType.class, query); +// assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test920DecisionsNotAnswered() throws Exception { + Session session = open(); + + try { + /* + * ### AccCertCase: Exists (decision: reviewerRef = XYZ and stage = ../stage and response is null or response = NO_RESPONSE) + */ + ObjectQuery query = ObjectQuery.createObjectQuery( + ExistsFilter.createExists( + new ItemPath(AccessCertificationCaseType.F_DECISION), + AccessCertificationCaseType.class, + prismContext, + AndFilter.createAnd( + RefFilter.createReferenceEqual( + AccessCertificationDecisionType.F_REVIEWER_REF, + AccessCertificationCaseType.class, + prismContext, + "123456"), + EqualFilter.createEqual( + new ItemPath(AccessCertificationDecisionType.F_STAGE_NUMBER), + AccessCertificationDecisionType.class, + prismContext, + null, + new ItemPath(PrismConstants.T_PARENT, AccessCertificationCaseType.F_CURRENT_RESPONSE_STAGE) + ), + OrFilter.createOr( + EqualFilter.createEqual( + AccessCertificationDecisionType.F_RESPONSE, + AccessCertificationDecisionType.class, + prismContext, null), + EqualFilter.createEqual( + AccessCertificationDecisionType.F_RESPONSE, + AccessCertificationDecisionType.class, + prismContext, AccessCertificationResponseType.NO_RESPONSE) + ) + ) + ) + ); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.decision d\n" + + "where\n" + + " (\n" + + " (\n" + + " d.reviewerRef.targetOid = :targetOid and\n" + + " d.reviewerRef.relation = :relation\n" + + " ) and\n" + + " (\n" + + " d.stageNumber = a.currentResponseStage or\n" + + " (\n" + + " d.stageNumber is null and\n" + + " a.currentResponseStage is null\n" + + " )\n" + + " ) and\n" + + " (\n" + + " d.response is null or\n" + + " d.response = :response\n" + + " )\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + // TODO negative tests - order by entity, reference, any, collection // TODO implement checks for "order by" for non-singletons diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 12ef921ec9e..7da95e2328c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -18,10 +18,8 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; -import com.evolveum.midpoint.repo.sql.data.common.container.RAssignment; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; -import com.evolveum.midpoint.repo.sql.data.common.other.RLookupTableRow; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -30,7 +28,6 @@ import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.ForeignKey; @@ -38,7 +35,6 @@ import javax.persistence.Entity; import javax.persistence.OneToMany; import javax.persistence.Table; -import javax.persistence.Transient; import javax.persistence.UniqueConstraint; import java.util.Collection; import java.util.HashSet; @@ -78,14 +74,14 @@ public void setDefinitionRef(REmbeddedReference definitionRef) { @OneToMany(mappedBy = RAccessCertificationCase.F_OWNER, orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getCases() { + public Set getCase() { if (cases == null) { cases = new HashSet<>(); } return cases; } - public void setCases(Set cases) { + public void setCase(Set cases) { this.cases = cases; } @@ -129,7 +125,7 @@ public static void copyFromJAXB(AccessCertificationCampaignType jaxb, RAccessCer case1.setCampaignRef(ObjectTypeUtil.createObjectRef(jaxb)); RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(repo, case1, generatorResult, prismContext); rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); - repo.getCases().add(rCase); + repo.getCase().add(rCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index f98f8f4a88d..438dda0e874 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -179,7 +179,7 @@ public XMLGregorianCalendar getRemediedTimestamp() { @OneToMany(mappedBy = RAccessCertificationDecision.F_OWNER, orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) - public Set getDecisions() { + public Set getDecision() { if (decisions == null) { decisions = new HashSet<>(); } @@ -230,7 +230,7 @@ public void setRemediedTimestamp(XMLGregorianCalendar remediedTimestamp) { this.remediedTimestamp = remediedTimestamp; } - public void setDecisions(Set decisions) { + public void setDecision(Set decisions) { this.decisions = decisions; } @@ -343,7 +343,7 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 rCase.setCurrentResponseStage(case1.getCurrentResponseStage()); for (AccessCertificationDecisionType decision : case1.getDecision()) { RAccessCertificationDecision rDecision = RAccessCertificationDecision.toRepo(rCase, decision, generatorResult, prismContext); - rCase.getDecisions().add(rDecision); + rCase.getDecision().add(rDecision); } PrismContainerValue cvalue = case1.asPrismContainerValue(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index e711ba92e43..c7d3354fe75 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -85,8 +85,8 @@ public void addCertificationCampaignCases(Session session, RObject object, boole if (merge) { deleteCertificationCampaignCases(session, campaign.getOid()); } - if (campaign.getCases() != null) { - for (RAccessCertificationCase aCase : campaign.getCases()) { + if (campaign.getCase() != null) { + for (RAccessCertificationCase aCase : campaign.getCase()) { session.save(aCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index 39321020504..68133ee7323 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -39,7 +39,7 @@ public class InterpretationContext { private PrismContext prismContext; private Session session; - private InterpreterHelper helper = new InterpreterHelper(this); + private ItemPathResolver itemPathResolver = new ItemPathResolver(this); private Class type; @@ -96,8 +96,8 @@ public RootHibernateQuery getHibernateQuery() { return hibernateQuery; } - public InterpreterHelper getHelper() { - return helper; + public ItemPathResolver getItemPathResolver() { + return itemPathResolver; } public JpaEntityDefinition getRootEntityDefinition() { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java new file mode 100644 index 00000000000..3685eb2b291 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.Validate; + +/** + * Describes current state in ItemPath resolution. + * + * We know what we've already resolved, and what remains to be done. + * We know which data element we're pointing to (entity, property, reference, any) and which JPA expression we can use to address it. + * We know last transition - how we got here. + * + * We also remember previous resolution state, in order to be able to go back via ".." path segment. + * + * @author mederly + */ +public class ItemPathResolutionState implements DebugDumpable { + + private static final Trace LOGGER = TraceManager.getTrace(ItemPathResolutionState.class); + + private ItemPath remainingItemPath; + + private String currentHqlPath; + private JpaDataNodeDefinition currentJpaNode; // where we are + private JpaLinkDefinition lastTransition; // how we got here (optional) + + private ItemPathResolutionState previousState; // from which state we got here (optional) + + private ItemPathResolver itemPathResolver; // provides auxiliary functionality + + public ItemPathResolutionState(ItemPath pathToResolve, String startingHqlPath, JpaEntityDefinition baseEntityDefinition, ItemPathResolver itemPathResolver) { + Validate.notNull(pathToResolve, "pathToResolve"); + Validate.notNull(startingHqlPath, "startingHqlPath"); + Validate.notNull(baseEntityDefinition, "baseEntityDefinition"); + Validate.notNull(itemPathResolver, "itemPathResolver"); + this.remainingItemPath = pathToResolve; + this.currentHqlPath = startingHqlPath; + this.currentJpaNode = baseEntityDefinition; + this.lastTransition = null; + this.previousState = null; + this.itemPathResolver = itemPathResolver; + } + + // no validation as this is private + private ItemPathResolutionState(ItemPath remainingItemPath, String currentHqlPath, JpaDataNodeDefinition currentJpaNode, JpaLinkDefinition lastTransition, ItemPathResolutionState previousState, ItemPathResolver itemPathResolver) { + this.remainingItemPath = remainingItemPath; + this.currentHqlPath = currentHqlPath; + this.currentJpaNode = currentJpaNode; + this.lastTransition = lastTransition; + this.previousState = previousState; + this.itemPathResolver = itemPathResolver; + } + + public ItemPath getRemainingItemPath() { + return remainingItemPath; + } + + public String getCurrentHqlPath() { + return currentHqlPath; + } + + public JpaDataNodeDefinition getCurrentJpaNode() { + return currentJpaNode; + } + + public JpaLinkDefinition getLastTransition() { + return lastTransition; + } + + public ItemPathResolutionState getPreviousState() { + return previousState; + } + + public boolean hasPreviousState() { + return previousState != null; + } + + public boolean isFinal() { + return ItemPath.isNullOrEmpty(remainingItemPath) || currentJpaNode instanceof JpaAnyDefinition; + } + + /** + * Precondition: !isFinal() + * Postcondition: non-null state + * @param singletonOnly Collections are forbidden + */ + public ItemPathResolutionState nextState(boolean singletonOnly) throws QueryException { + DataSearchResult result = currentJpaNode.nextLinkDefinition(remainingItemPath); + LOGGER.trace("nextLinkDefinition on '{}' returned '{}'", remainingItemPath, result != null ? result.getLinkDefinition() : "(null)"); + if (result == null) { // sorry we failed (however, this should be caught before -> so IllegalStateException) + throw new IllegalStateException("Couldn't find " + remainingItemPath + " in " + currentJpaNode); + } + JpaLinkDefinition linkDefinition = result.getLinkDefinition(); + String newHqlPath = currentHqlPath; + if (linkDefinition.hasJpaRepresentation()) { + if (singletonOnly && linkDefinition.isMultivalued()) { + throw new QueryException("Collections are not allowable for right-side paths"); // TODO better message + context + } + if (!linkDefinition.isEmbedded() || linkDefinition.isMultivalued()) { + LOGGER.trace("Adding join for '{}' to context", linkDefinition); + newHqlPath = itemPathResolver.addJoin(linkDefinition, currentHqlPath); + } else { + newHqlPath += "." + linkDefinition.getJpaName(); + } + } + ItemPathResolutionState next = new ItemPathResolutionState( + result.getRemainder(), + newHqlPath, + result.getTargetDefinition(), + result.getLinkDefinition(), + this, + itemPathResolver); + return next; + } + + @Override + public String debugDump() { + return debugDump(0); + } + + public String debugDumpNoParent() { + return debugDump(0, false); + } + + @Override + public String debugDump(int indent) { + return debugDump(indent, true); + } + + public String debugDump(int indent, boolean showParent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append("ItemPathResolutionState: Remaining path: ").append(remainingItemPath).append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("Current HQL path: ").append(currentHqlPath).append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("Current JPA data node: ").append(currentJpaNode).append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("Last transition: ").append(lastTransition).append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("Previous state: "); + if (previousState != null) { + if (showParent) { + sb.append("\n"); + sb.append(previousState.debugDump(indent + 2)); + } else { + sb.append(previousState).append("\n"); + } + } else { + sb.append("(null)\n"); + } + return sb.toString(); + } + + @Override + public String toString() { + return "ItemPathResolutionState{" + + "remainingItemPath=" + remainingItemPath + + ", currentHqlPath='" + currentHqlPath + '\'' + + ", currentJpaNode=" + currentJpaNode + + '}'; + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java similarity index 62% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java index 4cf8d4f2fc9..df672ad2184 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpreterHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java @@ -17,22 +17,16 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; -import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -42,68 +36,43 @@ import java.util.List; /** - * Various generally useful methods used within the interpretation algorithm. - * - * Note that this helper is context-specific. (Probably its name should reflect that.) + * Responsible for resolving item paths - i.e. translating them into JPA paths along with creation of necessary joins. + * Contains also methods that try to find proper specific entity definition when only general one (e.g. RObject) is provided. * * @author mederly */ -public class InterpreterHelper { +public class ItemPathResolver { - private static final Trace LOGGER = TraceManager.getTrace(InterpreterHelper.class); + private static final Trace LOGGER = TraceManager.getTrace(ItemPathResolver.class); private InterpretationContext context; - public InterpreterHelper(InterpretationContext interpretationContext) { + public ItemPathResolver(InterpretationContext interpretationContext) { this.context = interpretationContext; } - // returns property path that can be used to access the item values - public String prepareJoins(ItemPath relativePath, String currentHqlPath, JpaEntityDefinition baseEntityDefinition) throws QueryException { - - LOGGER.trace("Updating query context based on path '{}'", relativePath); - - /** - * We have to do something like this - examples: - * - activation.administrativeStatus -> (nothing, activation is embedded entity) - * - assignment.targetRef -> "left join u.assignments a with ..." - * - assignment.resourceRef -> "left join u.assignments a with ..." - * - organization -> "left join u.organization o" - * - * Or more complex: - * - assignment.modifyApproverRef -> "left join u.assignments a (...) left join a.modifyApproverRef m (...)" - * - assignment.target.longs -> "left join u.assignments a (...) left join a.target t left join t.longs (...)" - */ - - JpaDataNodeDefinition currentDefinition = baseEntityDefinition; - ItemPath itemPathRemainder = relativePath; - while (!ItemPath.isNullOrEmpty(itemPathRemainder) && !(currentDefinition instanceof JpaAnyDefinition)) { - LOGGER.trace("currentDefinition = '{}', current HQL path = '{}', itemPathRemainder = '{}'", currentDefinition, currentHqlPath, itemPathRemainder); - DataSearchResult result = currentDefinition.nextLinkDefinition(itemPathRemainder); - LOGGER.trace("nextLinkDefinition on '{}' returned '{}'", itemPathRemainder, result != null ? result.getLinkDefinition() : "(null)"); - if (result == null) { // sorry we failed (however, this should be caught before -> so IllegalStateException) - throw new IllegalStateException("Couldn't find " + itemPathRemainder + " in " + currentDefinition); - } - JpaLinkDefinition linkDefinition = result.getLinkDefinition(); - JpaDataNodeDefinition nextNodeDefinition = linkDefinition.getTargetDefinition(); + /** + * Resolves item path by creating a sequence of resolution states and preparing joins that are used to access JPA properties. + * "singletonOnly" means no collections are allowed (used for right-side path resolution). + */ + public ItemPathResolutionState resolveItemPath(ItemPath relativePath, String currentHqlPath, + JpaEntityDefinition baseEntityDefinition, + boolean singletonOnly) throws QueryException { - if (linkDefinition.hasJpaRepresentation()) { - if (!linkDefinition.isEmbedded() || linkDefinition.isMultivalued()) { - LOGGER.trace("Adding join for '{}' to context", linkDefinition); - currentHqlPath = addJoin(linkDefinition, currentHqlPath); - } else { - currentHqlPath += "." + linkDefinition.getJpaName(); - } - } - itemPathRemainder = result.getRemainder(); - currentDefinition = nextNodeDefinition; + ItemPathResolutionState currentState = new ItemPathResolutionState(relativePath, currentHqlPath, baseEntityDefinition, this); + + LOGGER.trace("Starting resolution and context update for item path '{}', singletonOnly='{}'", relativePath, singletonOnly); + + while (!currentState.isFinal()) { + LOGGER.trace("Current resolution state:\n{}", currentState.debugDumpNoParent()); + currentState = currentState.nextState(singletonOnly); } - LOGGER.trace("prepareJoins({}) returning currentHqlPath of '{}'", relativePath, currentHqlPath); - return currentHqlPath; + LOGGER.trace("resolveItemPath({}) returning final resolution state of:\n{}", relativePath, currentState.debugDump()); + return currentState; } - private String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) throws QueryException { + String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String joinedItemJpaName = joinedItemDefinition.getJpaName(); String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; @@ -154,23 +123,6 @@ private Object createQueryParamValue(VirtualQueryParam param) throws QueryExcept + param.name() + "' from String to '" + type + "', it's not yet implemented."); } - - public String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { - RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - String joinedItemJpaName = anyAssociationName; - String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); - - AndCondition conjunction = hibernateQuery.createAnd(); - if (ownerType != null) { // null for assignment extensions - conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType)); - } - conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); - - hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); - return joinedItemAlias; - } - /** * Finds the proper definition for (possibly abstract) entity. * Returns the most abstract entity that can be used. @@ -227,4 +179,24 @@ public JpaEntityDefinition findRestrictedEntityDefinition(JpaEntityDefinition ba } return specificEntityDefinition; } + + // @pre rightSidePath != null + public ItemPathResolutionState resolveRightItemPath(ItemPathResolutionState itemResolutionState, ItemPath rightSidePath) throws QueryException { + LOGGER.trace("Resolving right-side path of '{}' in state:\n{}", rightSidePath, itemResolutionState); + + // ItemPath may start with a sequence of ".." symbols - go backwards while necessary and possible + while (rightSidePath.startsWith(ParentPathSegment.class) && itemResolutionState.hasPreviousState()) { + itemResolutionState = itemResolutionState.getPreviousState(); + rightSidePath = rightSidePath.tail(); + } + + // Now the standard resolution should take place. But no collections! Target has to be a singleton. + if (!(itemResolutionState.getCurrentJpaNode() instanceof JpaEntityDefinition)) { + throw new IllegalStateException("Right-item path resolution cannot continue from non-entity node: " + itemResolutionState + " (internal error)"); + } + JpaEntityDefinition baseEntity = (JpaEntityDefinition) itemResolutionState.getCurrentJpaNode(); + ItemPathResolutionState state = resolveItemPath(rightSidePath, itemResolutionState.getCurrentHqlPath(), baseEntity, true); + LOGGER.trace("Resolved right-side path to {}", state); + return state; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index f1d9a33cf72..a6890191518 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -32,6 +32,7 @@ import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.prism.query.OrgFilter; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.prism.query.UndefinedFilter; @@ -190,7 +191,7 @@ private Restriction findAndCreateRestriction(T filter, LOGGER.trace("Determining restriction for filter {}", filter); - InterpreterHelper helper = context.getHelper(); + ItemPathResolver helper = context.getItemPathResolver(); JpaEntityDefinition baseEntityDefinition; if (parent != null) { baseEntityDefinition = parent.getBaseEntityDefinitionForChildren(); @@ -205,7 +206,7 @@ private Restriction findAndCreateRestriction(T filter, private Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext context, Restriction parent, - InterpreterHelper helper, JpaEntityDefinition baseEntityDefinition) throws QueryException { + ItemPathResolver helper, JpaEntityDefinition baseEntityDefinition) throws QueryException { // the order of processing restrictions can be important, so we do the selection via handwritten code @@ -228,20 +229,20 @@ Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext con ItemPath path = existsFilter.getFullPath(); ProperDataSearchResult searchResult = helper.findProperDataDefinition(baseEntityDefinition, path, JpaEntityDefinition.class); if (searchResult == null) { - throw new QueryException("Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity"); + throw new QueryException("Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity within " + baseEntityDefinition); } - return new ExistsRestriction(context, existsFilter, searchResult.getEntityDefinition(), parent, searchResult.getTargetDefinition()); + return new ExistsRestriction(context, existsFilter, searchResult.getEntityDefinition(), parent); } else if (filter instanceof RefFilter) { RefFilter refFilter = (RefFilter) filter; ItemPath path = refFilter.getFullPath(); ProperDataSearchResult searchResult = helper.findProperDataDefinition(baseEntityDefinition, path, JpaReferenceDefinition.class); if (searchResult == null) { - throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a reference item"); + throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a reference item within " + baseEntityDefinition); } return new ReferenceRestriction(context, refFilter, searchResult.getEntityDefinition(), parent, searchResult.getLinkDefinition()); - } else if (filter instanceof ValueFilter) { - ValueFilter valFilter = (ValueFilter) filter; + } else if (filter instanceof PropertyValueFilter) { + PropertyValueFilter valFilter = (PropertyValueFilter) filter; ItemPath path = valFilter.getFullPath(); ProperDataSearchResult propDefRes = helper.findProperDataDefinition(baseEntityDefinition, path, JpaPropertyDefinition.class); @@ -319,7 +320,7 @@ public void updatePagingAndSorting(InterpretationConte } } - ProperDataSearchResult result = context.getHelper().findProperDataDefinition( + ProperDataSearchResult result = context.getItemPathResolver().findProperDataDefinition( context.getRootEntityDefinition(), orderByPath, JpaDataNodeDefinition.class); if (result == null) { throw new QueryException("Unknown path '" + orderByPath + "', couldn't find definition for it, " @@ -340,7 +341,7 @@ public void updatePagingAndSorting(InterpretationConte JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition(); JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) targetDefinition; - String hqlPropertyPath = context.getHelper().prepareJoins(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition); + String hqlPropertyPath = context.getItemPathResolver().resolveItemPath(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition, false).getCurrentHqlPath(); if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java index 961a20c5677..fa35b054519 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.NotCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.PropertyPropertyComparisonCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.SimpleComparisonCondition; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -185,4 +186,7 @@ public Condition createIn(String propertyPath, String subqueryText) { return new InCondition(this, propertyPath, subqueryText); } + public Condition createEqXY(String leftSidePropertyPath, String rightSidePropertyPath, String operator, boolean ignoreCase) { + return new PropertyPropertyComparisonCondition(this, leftSidePropertyPath, rightSidePropertyPath, operator, ignoreCase); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java new file mode 100644 index 00000000000..4c4f34c8dc7 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.hqm.condition; + +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class PropertyPropertyComparisonCondition extends PropertyCondition { + + private String rightSidePath; + private String operator; + private boolean ignoreCase; + + public PropertyPropertyComparisonCondition(RootHibernateQuery rootHibernateQuery, String propertyPath, String rightSidePath, String operator, boolean ignoreCase) { + super(rootHibernateQuery, propertyPath); + Validate.notNull(rightSidePath, "rightSidePath"); + Validate.notNull(operator, "operator"); + this.rightSidePath = rightSidePath; + this.operator = operator; + this.ignoreCase = ignoreCase; + } + + @Override + public void dumpToHql(StringBuilder sb, int indent) { + HibernateQuery.indent(sb, indent); + + String finalPropertyPath; + String finalRightSidePropertyPath; + if (ignoreCase) { + finalPropertyPath = "lower(" + propertyPath + ")"; + finalRightSidePropertyPath = "lower(" + rightSidePath + ")"; + } else { + finalPropertyPath = propertyPath; + finalRightSidePropertyPath = rightSidePath; + } + + sb.append(finalPropertyPath).append(" ").append(operator).append(" ").append(finalRightSidePropertyPath); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index 7b3b5c9ec22..b3bb0c7c953 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -27,7 +27,11 @@ import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualAnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -44,7 +48,7 @@ public class AnyPropertyRestriction extends ItemValueRestriction { private JpaAnyDefinition jpaAnyDefinition; - public AnyPropertyRestriction(InterpretationContext context, ValueFilter filter, JpaEntityDefinition baseEntityDefinition, + public AnyPropertyRestriction(InterpretationContext context, PropertyValueFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent, JpaAnyDefinition jpaAnyDefinition) { super(context, filter, baseEntityDefinition, parent); Validate.notNull(jpaAnyDefinition, "anyDefinition"); @@ -52,7 +56,7 @@ public AnyPropertyRestriction(InterpretationContext context, ValueFilter filter, } @Override - public Condition interpretInternal(String hqlPath) throws QueryException { + public Condition interpretInternal() throws QueryException { ItemDefinition itemDefinition = filter.getDefinition(); QName itemName = itemDefinition.getName(); @@ -74,7 +78,8 @@ public Condition interpretInternal(String hqlPath) throws QueryException { } catch (SchemaException e) { throw new QueryException(e.getMessage(), e); } - String alias = getHelper().addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); + String hqlPath = getItemResolutionState().getCurrentHqlPath(); + String alias = addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); String propertyValuePath = alias + '.' + RAnyValue.F_VALUE; @@ -84,4 +89,21 @@ public Condition interpretInternal(String hqlPath) throws QueryException { return addIsNotNullIfNecessary(c, propertyValuePath); } + + private String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + String joinedItemJpaName = anyAssociationName; + String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; + String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); + + AndCondition conjunction = hibernateQuery.createAnd(); + if (ownerType != null) { // null for assignment extensions + conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType)); + } + conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); + + hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); + return joinedItemAlias; + } + } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java index c3d772f37d1..1653b25f1e8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.prism.query.ExistsFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -30,29 +31,19 @@ */ public class ExistsRestriction extends ItemRestriction { - /** - * Definition of the entity when this restriction starts. It is usually the same as rootEntityDefinition, - * but for Exists children it is the entity pointed to by Exists restriction. - * - * TODO think out the process of refinement of entity definition e.g. RObject->RUser - */ - private JpaEntityDefinition baseEntityDefinitionForChildren; - - /** - * HQL path to be used for child restrictions. - */ - private String baseHqlPathForChildren; - public ExistsRestriction(InterpretationContext context, ExistsFilter filter, JpaEntityDefinition baseEntityDefinition, - Restriction parent, JpaEntityDefinition baseEntityDefinitionForChildren) { - super(context, filter, baseEntityDefinition, parent); - Validate.notNull(baseEntityDefinitionForChildren, "baseEntityDefinitionForChildren"); - this.baseEntityDefinitionForChildren = baseEntityDefinitionForChildren; + Restriction parent) { + super(context, filter, filter.getFullPath(), baseEntityDefinition, parent); } @Override public Condition interpret() throws QueryException { - baseHqlPathForChildren = getHelper().prepareJoins(filter.getFullPath(), getBaseHqlPath(), baseEntityDefinition); + ItemPathResolutionState resolutionState = getItemPathResolver().resolveItemPath(filter.getFullPath(), getBaseHqlPath(), baseEntityDefinition, false); + if (!(resolutionState.getCurrentJpaNode() instanceof JpaEntityDefinition)) { + // should be checked when instantiating this restriction + throw new IllegalStateException("Internal error - resolutionState for ExistsRestriction points to non-entity node: " + resolutionState.getCurrentJpaNode()); + } + setItemResolutionState(resolutionState); InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); @@ -61,7 +52,7 @@ public Condition interpret() throws QueryException { @Override public String getBaseHqlPathForChildren() { - return baseHqlPathForChildren; + return getItemResolutionState().getCurrentHqlPath(); } @Override @@ -71,6 +62,11 @@ public ItemPath getBaseItemPathForChildren() { @Override public JpaEntityDefinition getBaseEntityDefinitionForChildren() { - return baseEntityDefinitionForChildren; + return (JpaEntityDefinition) getItemResolutionState().getCurrentJpaNode(); + } + + @Override + public ItemPathResolutionState getItemPathResolutionStateForChildren() { + return getItemResolutionState(); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index 86f196cbacf..cf6c81483b9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -16,16 +16,52 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import org.apache.commons.lang.Validate; /** + * Base for all item path-related restrictions, e.g. those that are based on item path that points to a JPA data node. + * * @author mederly */ public abstract class ItemRestriction extends Restriction { - public ItemRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { + /** + * Item path (relative to parent restriction), copied from the appropriate filter. + * Not null, although possibly empty. + */ + private ItemPath itemPath; + + /** + * Item resolution state, i.e. "how we got to the given item". + * Necessary to enable looking upwards via ".." operator. + * Filled-in within interpret() method. + */ + private ItemPathResolutionState itemResolutionState; + + public ItemRestriction(InterpretationContext context, T filter, ItemPath itemPath, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); + if (itemPath != null) { + this.itemPath = itemPath; + } else { + this.itemPath = ItemPath.EMPTY_PATH; + } + } + + public ItemPath getItemPath() { + return itemPath; + } + + public ItemPathResolutionState getItemResolutionState() { + return itemResolutionState; + } + + public void setItemResolutionState(ItemPathResolutionState itemResolutionState) { + Validate.notNull(itemResolutionState); + this.itemResolutionState = itemResolutionState; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java index 2e9c5cc3d56..ce44753b0c4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -19,33 +19,25 @@ import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.GreaterFilter; import com.evolveum.midpoint.prism.query.LessFilter; -import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.ValueFilter; -import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; -import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNotNullCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.IsNullCondition; import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; -import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.apache.commons.lang.ClassUtils; -import javax.xml.namespace.QName; import java.util.List; /** @@ -64,25 +56,26 @@ public abstract class ItemValueRestriction extends ItemRe private static final Trace LOGGER = TraceManager.getTrace(ItemValueRestriction.class); public ItemValueRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { - super(context, filter, baseEntityDefinition, parent); + super(context, filter, filter.getFullPath(), baseEntityDefinition, parent); } @Override public Condition interpret() throws QueryException { - ItemPath path = filter.getFullPath(); + ItemPath path = getItemPath(); if (ItemPath.isNullOrEmpty(path)) { throw new QueryException("Null or empty path for ItemValueRestriction in " + filter.debugDump()); } - String hqlPropertyPath = getHelper().prepareJoins(path, getBaseHqlPath(), baseEntityDefinition); + ItemPathResolutionState resolutionState = getItemPathResolver().resolveItemPath(path, getBaseHqlPath(), baseEntityDefinition, false); + setItemResolutionState(resolutionState); - Condition condition = interpretInternal(hqlPropertyPath); + Condition condition = interpretInternal(); return condition; } - public abstract Condition interpretInternal(String hqlPath) throws QueryException; + public abstract Condition interpretInternal() throws QueryException; - protected Condition createCondition(String propertyName, Object value, ValueFilter filter) throws QueryException { + protected Condition createCondition(String hqlPropertyPath, Object value, ValueFilter filter) throws QueryException { ItemRestrictionOperation operation; if (filter instanceof EqualFilter) { operation = ItemRestrictionOperation.EQ; @@ -113,8 +106,8 @@ protected Condition createCondition(String propertyName, Object value, ValueFilt if (filter.getMatchingRule() != null){ matchingRule = filter.getMatchingRule().getLocalPart(); } - - return matcher.match(context.getHibernateQuery(), operation, propertyName, value, matchingRule); + + return matcher.match(context.getHibernateQuery(), operation, hqlPropertyPath, value, matchingRule); } protected Object getValue(List values) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index 73d50376048..6ea773dd793 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -16,16 +16,23 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; +import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -34,17 +41,18 @@ import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; +import java.util.List; /** * @author lazyman */ -public class PropertyRestriction extends ItemValueRestriction { +public class PropertyRestriction extends ItemValueRestriction { private static final Trace LOGGER = TraceManager.getTrace(PropertyRestriction.class); private JpaLinkDefinition linkDefinition; - public PropertyRestriction(InterpretationContext context, ValueFilter filter, JpaEntityDefinition baseEntityDefinition, + public PropertyRestriction(InterpretationContext context, PropertyValueFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent, JpaLinkDefinition linkDefinition) { super(context, filter, baseEntityDefinition, parent); Validate.notNull(linkDefinition, "linkDefinition"); @@ -52,16 +60,40 @@ public PropertyRestriction(InterpretationContext context, ValueFilter filter, Jp } @Override - public Condition interpretInternal(String hqlPath) throws QueryException { + public Condition interpretInternal() throws QueryException { if (linkDefinition.getTargetDefinition().isLob()) { throw new QueryException("Can't query based on clob property value '" + linkDefinition + "'."); } + List values = filter.getValues(); + if (values != null && values.size() > 1) { + throw new QueryException("Filter '" + filter + "' contain more than one value (which is not supported for now)."); + } - Object value = getValueFromFilter(filter); - Condition condition = createCondition(hqlPath, value, filter); - - return addIsNotNullIfNecessary(condition, hqlPath); + String leftHqlPath = getItemResolutionState().getCurrentHqlPath(); + if (filter.getRightSidePath() != null) { + if (!(filter instanceof EqualFilter)) { + throw new QueryException("Right-side ItemPath is supported currently only for EqualFilter, not for " + filter); + } + ItemPathResolutionState rightItemState = getItemPathResolver().resolveRightItemPath( + getItemPathResolutionStateForChildren(), filter.getRightSidePath()); + String rightHqlPath = rightItemState.getCurrentHqlPath(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + // left = right OR (left IS NULL AND right IS NULL) + Condition condition = hibernateQuery.createEqXY(leftHqlPath, rightHqlPath, "=", false); + OrCondition orCondition = hibernateQuery.createOr( + condition, + hibernateQuery.createAnd( + hibernateQuery.createIsNull(leftHqlPath), + hibernateQuery.createIsNull(rightHqlPath) + ) + ); + return orCondition; + } else { + Object value = getValueFromFilter(filter); + Condition condition = createCondition(leftHqlPath, value, filter); + return addIsNotNullIfNecessary(condition, leftHqlPath); + } } protected Object getValueFromFilter(ValueFilter filter) throws QueryException { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index ea1c67e1e7d..44ad54a13bc 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -56,8 +56,9 @@ public ReferenceRestriction(InterpretationContext context, RefFilter filter, Jpa } @Override - public Condition interpretInternal(String hqlPath) throws QueryException { + public Condition interpretInternal() throws QueryException { + String hqlPath = getItemResolutionState().getCurrentHqlPath(); LOGGER.trace("interpretInternal starting with hqlPath = {}", hqlPath); List values = filter.getValues(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index 7746a8f07db..d90dbbb57b9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -21,7 +21,8 @@ import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.InterpreterHelper; +import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; +import com.evolveum.midpoint.repo.sql.query2.ItemPathResolver; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import org.apache.commons.lang.Validate; @@ -184,8 +185,22 @@ public JpaEntityDefinition getBaseEntityDefinitionForChildren() { return getBaseEntityDefinition(); } - protected InterpreterHelper getHelper() { - return getContext().getHelper(); + // temporary hack - TODO implement more seriously + public ItemPathResolutionState getItemPathResolutionStateForChildren() { + if (parent != null) { + return parent.getItemPathResolutionStateForChildren(); + } else { + return new ItemPathResolutionState( + ItemPath.EMPTY_PATH, // this is dummy + getBaseHqlPath(), + getBaseEntityDefinition(), + getItemPathResolver() + ); + } + } + + protected ItemPathResolver getItemPathResolver() { + return getContext().getItemPathResolver(); } // /** From e55b27799b0e4268b79934675baceab3231a61a9 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 1 Dec 2015 23:33:24 +0100 Subject: [PATCH 053/116] Cleaned up support for Equal(x, y) a bit. Not really finished yet. --- .../repo/sql/QueryInterpreter2Test.java | 6 +- .../repo/sql/query2/HqlDataInstance.java | 117 ++++++++++++ .../repo/sql/query2/HqlEntityInstance.java | 45 +++++ .../sql/query2/ItemPathResolutionState.java | 108 +++++------ .../repo/sql/query2/ItemPathResolver.java | 36 ++-- .../repo/sql/query2/QueryInterpreter2.java | 6 +- .../restriction/AnyPropertyRestriction.java | 2 +- .../query2/restriction/ExistsRestriction.java | 34 ++-- .../query2/restriction/InOidRestriction.java | 8 +- .../query2/restriction/ItemRestriction.java | 19 +- .../restriction/ItemValueRestriction.java | 6 +- .../query2/restriction/OrgRestriction.java | 4 +- .../restriction/PropertyRestriction.java | 11 +- .../restriction/ReferenceRestriction.java | 2 +- .../sql/query2/restriction/Restriction.java | 171 +++++------------- .../query2/restriction/TypeRestriction.java | 2 +- 16 files changed, 301 insertions(+), 276 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 9bf1637ace2..4e25a1d134c 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -2779,7 +2779,7 @@ public void test910PreferredLanguageEqualsCostCenter() throws Exception { } } - @Test + @Test(enabled = false) public void test915OrganizationEqualsCostCenter() throws Exception { Session session = open(); @@ -2875,10 +2875,6 @@ public void test920DecisionsNotAnswered() throws Exception { // TODO negative tests - order by entity, reference, any, collection // TODO implement checks for "order by" for non-singletons - // TODO search for "no decision" condition (V2) - // TODO sorting based on referenced entity names (V2) - // TODO for cases: sorting based on object name, target name, campaign name (!) (V2-3) - protected String getInterpretedQuery2(Session session, Class type, File file) throws Exception { return getInterpretedQuery2(session, type, file, false); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java new file mode 100644 index 00000000000..b84ef997679 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.Validate; + +/** + * Describes result of ItemPath resolution: HQL property path + current data node definition. + * Points to parent data item (i.e. the one that corresponds to parent ItemPath translation), + * just in case we would like to go back via ".." operator. + * + * This differs from JpaDefinitions in that it points to a specific HQL property used in the + * query being constructed. + * + * This object is unmodifiable. + * + * @author mederly + */ +public class HqlDataInstance implements DebugDumpable { + + private static final Trace LOGGER = TraceManager.getTrace(HqlDataInstance.class); + + final protected String hqlPath; + final protected D jpaDefinition; + final protected HqlDataInstance parentDataItem; // optional + + public HqlDataInstance(String hqlPath, D jpaDefinition, + HqlDataInstance parentDataItem) { + Validate.notNull(hqlPath, "hqlPath"); + Validate.notNull(jpaDefinition, "jpaDefinition"); + this.hqlPath = hqlPath; + this.jpaDefinition = jpaDefinition; + this.parentDataItem = parentDataItem; + } + + public String getHqlPath() { + return hqlPath; + } + + public D getJpaDefinition() { + return jpaDefinition; + } + + public HqlDataInstance getParentItem() { + return parentDataItem; + } + + @Override + public String debugDump() { + return debugDump(0); + } + + public String debugDumpNoParent() { + return debugDump(0, false); + } + + @Override + public String debugDump(int indent) { + return debugDump(indent, true); + } + + public String debugDump(int indent, boolean showParent) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append("HqlDataInstance:\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("HQL path: ").append(hqlPath).append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("JPA definition: ").append(jpaDefinition).append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append("Previous result: "); + if (parentDataItem != null) { + if (showParent) { + sb.append("\n"); + sb.append(parentDataItem.debugDump(indent + 2)); + } else { + sb.append(parentDataItem).append("\n"); + } + } else { + sb.append("(null)\n"); + } + return sb.toString(); + } + + @Override + public String toString() { + return "HqlDataInstance{" + + "hqlPath='" + hqlPath + '\'' + + ", jpaDefinition=" + jpaDefinition + + ", parentDataItem=(" + (parentDataItem != null ? parentDataItem.hqlPath : "none") + + ")}"; + } + + public HqlEntityInstance asHqlEntityInstance() { + return new HqlEntityInstance(hqlPath, (JpaEntityDefinition) jpaDefinition, parentDataItem); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java new file mode 100644 index 00000000000..ab118eb4fbe --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2; + +import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; +import org.apache.commons.lang.Validate; + +/** + * @author mederly + */ +public class HqlEntityInstance extends HqlDataInstance { + + public HqlEntityInstance(String hqlPath, JpaEntityDefinition jpaDefinition, HqlDataInstance parentPropertyPath) { + super(hqlPath, jpaDefinition, parentPropertyPath); + } + + public HqlEntityInstance narrowFor(JpaEntityDefinition overridingDefinition) { + Validate.notNull(overridingDefinition, "overridingDefinition"); + + if (overridingDefinition.isAssignableFrom(jpaDefinition)) { + // nothing to do here + return this; + } else if (jpaDefinition.isAssignableFrom(overridingDefinition)) { + return new HqlEntityInstance(hqlPath, overridingDefinition, parentDataItem); + } else { + throw new IllegalStateException("Illegal attempt to narrow entity definition: from " + jpaDefinition + + " to " + overridingDefinition + ". These two definitions are not compatible."); + } + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java index 3685eb2b291..3f5fdc9a374 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java @@ -17,10 +17,10 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; @@ -31,11 +31,11 @@ /** * Describes current state in ItemPath resolution. * - * We know what we've already resolved, and what remains to be done. - * We know which data element we're pointing to (entity, property, reference, any) and which JPA expression we can use to address it. + * We know what remains to be resolved. + * We know the HQL item we are pointing to. * We know last transition - how we got here. * - * We also remember previous resolution state, in order to be able to go back via ".." path segment. + * This object is unmodifiable. * * @author mederly */ @@ -43,36 +43,19 @@ public class ItemPathResolutionState implements DebugDumpable { private static final Trace LOGGER = TraceManager.getTrace(ItemPathResolutionState.class); - private ItemPath remainingItemPath; + final private ItemPath remainingItemPath; + final private HqlDataInstance hqlDataInstance; + final private JpaLinkDefinition lastTransition; // how we got here (optional) - private String currentHqlPath; - private JpaDataNodeDefinition currentJpaNode; // where we are - private JpaLinkDefinition lastTransition; // how we got here (optional) + final private ItemPathResolver itemPathResolver; // provides auxiliary functionality - private ItemPathResolutionState previousState; // from which state we got here (optional) - - private ItemPathResolver itemPathResolver; // provides auxiliary functionality - - public ItemPathResolutionState(ItemPath pathToResolve, String startingHqlPath, JpaEntityDefinition baseEntityDefinition, ItemPathResolver itemPathResolver) { + public ItemPathResolutionState(ItemPath pathToResolve, HqlDataInstance hqlDataInstance, ItemPathResolver itemPathResolver) { Validate.notNull(pathToResolve, "pathToResolve"); - Validate.notNull(startingHqlPath, "startingHqlPath"); - Validate.notNull(baseEntityDefinition, "baseEntityDefinition"); + Validate.notNull(hqlDataInstance, "hqlDataInstance"); Validate.notNull(itemPathResolver, "itemPathResolver"); this.remainingItemPath = pathToResolve; - this.currentHqlPath = startingHqlPath; - this.currentJpaNode = baseEntityDefinition; + this.hqlDataInstance = hqlDataInstance; this.lastTransition = null; - this.previousState = null; - this.itemPathResolver = itemPathResolver; - } - - // no validation as this is private - private ItemPathResolutionState(ItemPath remainingItemPath, String currentHqlPath, JpaDataNodeDefinition currentJpaNode, JpaLinkDefinition lastTransition, ItemPathResolutionState previousState, ItemPathResolver itemPathResolver) { - this.remainingItemPath = remainingItemPath; - this.currentHqlPath = currentHqlPath; - this.currentJpaNode = currentJpaNode; - this.lastTransition = lastTransition; - this.previousState = previousState; this.itemPathResolver = itemPathResolver; } @@ -80,60 +63,66 @@ public ItemPath getRemainingItemPath() { return remainingItemPath; } - public String getCurrentHqlPath() { - return currentHqlPath; - } - - public JpaDataNodeDefinition getCurrentJpaNode() { - return currentJpaNode; + public HqlDataInstance getHqlDataInstance() { + return hqlDataInstance; } public JpaLinkDefinition getLastTransition() { return lastTransition; } - public ItemPathResolutionState getPreviousState() { - return previousState; - } - - public boolean hasPreviousState() { - return previousState != null; + public ItemPathResolver getItemPathResolver() { + return itemPathResolver; } public boolean isFinal() { - return ItemPath.isNullOrEmpty(remainingItemPath) || currentJpaNode instanceof JpaAnyDefinition; + return ItemPath.isNullOrEmpty(remainingItemPath) || hqlDataInstance.getJpaDefinition() instanceof JpaAnyDefinition; } /** + * Executes transition to next state. Modifies query context by adding joins as necessary. + * * Precondition: !isFinal() - * Postcondition: non-null state + * Precondition: adequate transition exists + * * @param singletonOnly Collections are forbidden + * @return destination state - always not null */ public ItemPathResolutionState nextState(boolean singletonOnly) throws QueryException { - DataSearchResult result = currentJpaNode.nextLinkDefinition(remainingItemPath); + + // special case - ".." when having previous state means returning to that state + // used e.g. for Exists (some-path, some-conditions AND Equals(../xxx, yyy)) + // + // This is brutal hack, to be thought again. + if (remainingItemPath.startsWith(ParentPathSegment.class) && hqlDataInstance.getParentItem() != null) { + ItemPathResolutionState next = new ItemPathResolutionState( + remainingItemPath.tail(), + hqlDataInstance.getParentItem(), + itemPathResolver); + return next; + + } + DataSearchResult result = hqlDataInstance.getJpaDefinition().nextLinkDefinition(remainingItemPath); LOGGER.trace("nextLinkDefinition on '{}' returned '{}'", remainingItemPath, result != null ? result.getLinkDefinition() : "(null)"); if (result == null) { // sorry we failed (however, this should be caught before -> so IllegalStateException) - throw new IllegalStateException("Couldn't find " + remainingItemPath + " in " + currentJpaNode); + throw new IllegalStateException("Couldn't find " + remainingItemPath + " in " + hqlDataInstance.getJpaDefinition()); } JpaLinkDefinition linkDefinition = result.getLinkDefinition(); - String newHqlPath = currentHqlPath; + String newHqlPath = hqlDataInstance.getHqlPath(); if (linkDefinition.hasJpaRepresentation()) { if (singletonOnly && linkDefinition.isMultivalued()) { throw new QueryException("Collections are not allowable for right-side paths"); // TODO better message + context } if (!linkDefinition.isEmbedded() || linkDefinition.isMultivalued()) { LOGGER.trace("Adding join for '{}' to context", linkDefinition); - newHqlPath = itemPathResolver.addJoin(linkDefinition, currentHqlPath); + newHqlPath = itemPathResolver.addJoin(linkDefinition, hqlDataInstance.getHqlPath()); } else { newHqlPath += "." + linkDefinition.getJpaName(); } } ItemPathResolutionState next = new ItemPathResolutionState( result.getRemainder(), - newHqlPath, - result.getTargetDefinition(), - result.getLinkDefinition(), - this, + new HqlDataInstance(newHqlPath, result.getTargetDefinition(), hqlDataInstance), itemPathResolver); return next; } @@ -157,23 +146,9 @@ public String debugDump(int indent, boolean showParent) { DebugUtil.indentDebugDump(sb, indent); sb.append("ItemPathResolutionState: Remaining path: ").append(remainingItemPath).append("\n"); DebugUtil.indentDebugDump(sb, indent + 1); - sb.append("Current HQL path: ").append(currentHqlPath).append("\n"); - DebugUtil.indentDebugDump(sb, indent + 1); - sb.append("Current JPA data node: ").append(currentJpaNode).append("\n"); - DebugUtil.indentDebugDump(sb, indent + 1); sb.append("Last transition: ").append(lastTransition).append("\n"); DebugUtil.indentDebugDump(sb, indent + 1); - sb.append("Previous state: "); - if (previousState != null) { - if (showParent) { - sb.append("\n"); - sb.append(previousState.debugDump(indent + 2)); - } else { - sb.append(previousState).append("\n"); - } - } else { - sb.append("(null)\n"); - } + sb.append("HQL data item: ").append(hqlDataInstance.debugDump(indent + 2, showParent)); return sb.toString(); } @@ -181,8 +156,7 @@ public String debugDump(int indent, boolean showParent) { public String toString() { return "ItemPathResolutionState{" + "remainingItemPath=" + remainingItemPath + - ", currentHqlPath='" + currentHqlPath + '\'' + - ", currentJpaNode=" + currentJpaNode + + ", hqlDataInstance='" + hqlDataInstance + '\'' + '}'; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java index df672ad2184..578e7178da0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java @@ -53,13 +53,20 @@ public ItemPathResolver(InterpretationContext interpretationContext) { /** * Resolves item path by creating a sequence of resolution states and preparing joins that are used to access JPA properties. - * "singletonOnly" means no collections are allowed (used for right-side path resolution). + * "singletonOnly" means no collections are allowed (used for right-side path resolution and order criteria). */ - public ItemPathResolutionState resolveItemPath(ItemPath relativePath, String currentHqlPath, + public HqlDataInstance resolveItemPath(ItemPath relativePath, String currentHqlPath, JpaEntityDefinition baseEntityDefinition, boolean singletonOnly) throws QueryException { + HqlDataInstance baseDataInstance = new HqlDataInstance(currentHqlPath, baseEntityDefinition, null); + return resolveItemPath(relativePath, baseDataInstance, singletonOnly); + } + + public HqlDataInstance resolveItemPath(ItemPath relativePath, + HqlDataInstance baseDataInstance, + boolean singletonOnly) throws QueryException { - ItemPathResolutionState currentState = new ItemPathResolutionState(relativePath, currentHqlPath, baseEntityDefinition, this); + ItemPathResolutionState currentState = new ItemPathResolutionState(relativePath, baseDataInstance, this); LOGGER.trace("Starting resolution and context update for item path '{}', singletonOnly='{}'", relativePath, singletonOnly); @@ -68,8 +75,8 @@ public ItemPathResolutionState resolveItemPath(ItemPath relativePath, String cur currentState = currentState.nextState(singletonOnly); } - LOGGER.trace("resolveItemPath({}) returning final resolution state of:\n{}", relativePath, currentState.debugDump()); - return currentState; + LOGGER.trace("resolveItemPath({}) ending in resolution state of:\n{}", relativePath, currentState.debugDump()); + return currentState.getHqlDataInstance(); } String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) throws QueryException { @@ -180,23 +187,4 @@ public JpaEntityDefinition findRestrictedEntityDefinition(JpaEntityDefinition ba return specificEntityDefinition; } - // @pre rightSidePath != null - public ItemPathResolutionState resolveRightItemPath(ItemPathResolutionState itemResolutionState, ItemPath rightSidePath) throws QueryException { - LOGGER.trace("Resolving right-side path of '{}' in state:\n{}", rightSidePath, itemResolutionState); - - // ItemPath may start with a sequence of ".." symbols - go backwards while necessary and possible - while (rightSidePath.startsWith(ParentPathSegment.class) && itemResolutionState.hasPreviousState()) { - itemResolutionState = itemResolutionState.getPreviousState(); - rightSidePath = rightSidePath.tail(); - } - - // Now the standard resolution should take place. But no collections! Target has to be a singleton. - if (!(itemResolutionState.getCurrentJpaNode() instanceof JpaEntityDefinition)) { - throw new IllegalStateException("Right-item path resolution cannot continue from non-entity node: " + itemResolutionState + " (internal error)"); - } - JpaEntityDefinition baseEntity = (JpaEntityDefinition) itemResolutionState.getCurrentJpaNode(); - ItemPathResolutionState state = resolveItemPath(rightSidePath, itemResolutionState.getCurrentHqlPath(), baseEntity, true); - LOGGER.trace("Resolved right-side path to {}", state); - return state; - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index a6890191518..a87dfb25a2a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -194,7 +194,7 @@ private Restriction findAndCreateRestriction(T filter, ItemPathResolver helper = context.getItemPathResolver(); JpaEntityDefinition baseEntityDefinition; if (parent != null) { - baseEntityDefinition = parent.getBaseEntityDefinitionForChildren(); + baseEntityDefinition = parent.getBaseHqlEntityForChildren().getJpaDefinition(); } else { baseEntityDefinition = context.getRootEntityDefinition(); } @@ -341,7 +341,9 @@ public void updatePagingAndSorting(InterpretationConte JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition(); JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) targetDefinition; - String hqlPropertyPath = context.getItemPathResolver().resolveItemPath(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition, false).getCurrentHqlPath(); + String hqlPropertyPath = context.getItemPathResolver() + .resolveItemPath(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition, true) + .getHqlPath(); if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index b3bb0c7c953..b05e217da5a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -78,7 +78,7 @@ public Condition interpretInternal() throws QueryException { } catch (SchemaException e) { throw new QueryException(e.getMessage(), e); } - String hqlPath = getItemResolutionState().getCurrentHqlPath(); + String hqlPath = getHqlDataInstance().getHqlPath(); String alias = addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); String propertyValuePath = alias + '.' + RAnyValue.F_VALUE; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java index 1653b25f1e8..47b3e093015 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java @@ -19,18 +19,21 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ExistsFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; +import com.evolveum.midpoint.repo.sql.query2.HqlEntityInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import org.apache.commons.lang.Validate; /** * @author mederly */ public class ExistsRestriction extends ItemRestriction { + + public ExistsRestriction(InterpretationContext context, ExistsFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, filter.getFullPath(), baseEntityDefinition, parent); @@ -38,12 +41,12 @@ public ExistsRestriction(InterpretationContext context, ExistsFilter filter, Jpa @Override public Condition interpret() throws QueryException { - ItemPathResolutionState resolutionState = getItemPathResolver().resolveItemPath(filter.getFullPath(), getBaseHqlPath(), baseEntityDefinition, false); - if (!(resolutionState.getCurrentJpaNode() instanceof JpaEntityDefinition)) { - // should be checked when instantiating this restriction - throw new IllegalStateException("Internal error - resolutionState for ExistsRestriction points to non-entity node: " + resolutionState.getCurrentJpaNode()); + HqlDataInstance dataInstance = getItemPathResolver().resolveItemPath(filter.getFullPath(), getBaseHqlEntity(), false); + if (!(dataInstance.getJpaDefinition() instanceof JpaEntityDefinition)) { + // should be checked when instantiating this restriction, so now we can throw hard exception + throw new IllegalStateException("Internal error - resolutionState for ExistsRestriction points to non-entity node: " + dataInstance.getJpaDefinition()); } - setItemResolutionState(resolutionState); + setHqlDataInstance(dataInstance); InterpretationContext context = getContext(); QueryInterpreter2 interpreter = context.getInterpreter(); @@ -51,22 +54,7 @@ public Condition interpret() throws QueryException { } @Override - public String getBaseHqlPathForChildren() { - return getItemResolutionState().getCurrentHqlPath(); - } - - @Override - public ItemPath getBaseItemPathForChildren() { - return new ItemPath(getBaseItemPath(), filter.getFullPath()); - } - - @Override - public JpaEntityDefinition getBaseEntityDefinitionForChildren() { - return (JpaEntityDefinition) getItemResolutionState().getCurrentJpaNode(); - } - - @Override - public ItemPathResolutionState getItemPathResolutionStateForChildren() { - return getItemResolutionState(); + public HqlEntityInstance getBaseHqlEntityForChildren() { + return hqlDataInstance.asHqlEntityInstance(); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java index 6f0cd01f390..d8eca43f8a1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/InOidRestriction.java @@ -39,21 +39,21 @@ public InOidRestriction(InterpretationContext context, InOidFilter filter, JpaEn @Override public Condition interpret() throws QueryException { - String hqlPath = getBaseHqlPath() + "."; + String hqlPath = getBaseHqlEntity().getHqlPath() + "."; Collection idValues; // TODO check applicability if (filter.isConsiderOwner()) { hqlPath += "ownerOid"; idValues = filter.getOids(); - } else if (RObject.class.isAssignableFrom(baseEntityDefinition.getJpaClass())) { + } else if (RObject.class.isAssignableFrom(getBaseHqlEntity().getJpaDefinition().getJpaClass())) { hqlPath += "oid"; idValues = filter.getOids(); - } else if (Container.class.isAssignableFrom(baseEntityDefinition.getJpaClass())) { + } else if (Container.class.isAssignableFrom(getBaseHqlEntity().getJpaDefinition().getJpaClass())) { hqlPath += "id"; // quite a hack idValues = toIntList(filter.getOids()); } else { - throw new QueryException("InOidRestriction cannot be applied to the entity: " + baseEntityDefinition); + throw new QueryException("InOidRestriction cannot be applied to the entity: " + getBaseHqlEntity()); } return getContext().getHibernateQuery().createIn(hqlPath, idValues); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index cf6c81483b9..919547e5815 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; @@ -34,14 +35,14 @@ public abstract class ItemRestriction extends Restrictio * Item path (relative to parent restriction), copied from the appropriate filter. * Not null, although possibly empty. */ - private ItemPath itemPath; + final protected ItemPath itemPath; /** - * Item resolution state, i.e. "how we got to the given item". - * Necessary to enable looking upwards via ".." operator. + * Information about resolved itemPath. Needed when accessing the data. + * Contains also information on previous steps, useful to enable looking upwards via ".." operator. * Filled-in within interpret() method. */ - private ItemPathResolutionState itemResolutionState; + protected HqlDataInstance hqlDataInstance; public ItemRestriction(InterpretationContext context, T filter, ItemPath itemPath, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); @@ -56,12 +57,12 @@ public ItemPath getItemPath() { return itemPath; } - public ItemPathResolutionState getItemResolutionState() { - return itemResolutionState; + public HqlDataInstance getHqlDataInstance() { + return hqlDataInstance; } - public void setItemResolutionState(ItemPathResolutionState itemResolutionState) { - Validate.notNull(itemResolutionState); - this.itemResolutionState = itemResolutionState; + public void setHqlDataInstance(HqlDataInstance hqlDataInstance) { + Validate.notNull(hqlDataInstance); + this.hqlDataInstance = hqlDataInstance; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java index ce44753b0c4..937eff93007 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -25,8 +25,8 @@ import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; @@ -66,8 +66,8 @@ public Condition interpret() throws QueryException { if (ItemPath.isNullOrEmpty(path)) { throw new QueryException("Null or empty path for ItemValueRestriction in " + filter.debugDump()); } - ItemPathResolutionState resolutionState = getItemPathResolver().resolveItemPath(path, getBaseHqlPath(), baseEntityDefinition, false); - setItemResolutionState(resolutionState); + HqlDataInstance dataInstance = getItemPathResolver().resolveItemPath(path, getBaseHqlEntity(), false); + setHqlDataInstance(dataInstance); Condition condition = interpretInternal(); return condition; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java index 59721e8e475..469f6c363b2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/OrgRestriction.java @@ -38,7 +38,7 @@ public Condition interpret() throws QueryException { RootHibernateQuery hibernateQuery = getContext().getHibernateQuery(); if (filter.isRoot()) { // oid in (select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1) - return hibernateQuery.createIn(getBaseHqlPath() + ".oid", + return hibernateQuery.createIn(getBaseHqlEntity().getHqlPath() + ".oid", "select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1"); } @@ -71,6 +71,6 @@ public Condition interpret() throws QueryException { "ref.targetOid in (" + "select descendantOid from ROrgClosure where ancestorOid = :" + orgOidParamName + ")"; } - return hibernateQuery.createIn(getBaseHqlPath() + ".oid", oidQueryText); + return hibernateQuery.createIn(getBaseHqlEntity().getHqlPath() + ".oid", oidQueryText); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index 6ea773dd793..63d8b395530 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -23,14 +23,13 @@ import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; -import com.evolveum.midpoint.repo.sql.query2.hqm.HibernateQuery; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.OrCondition; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -70,14 +69,14 @@ public Condition interpretInternal() throws QueryException { throw new QueryException("Filter '" + filter + "' contain more than one value (which is not supported for now)."); } - String leftHqlPath = getItemResolutionState().getCurrentHqlPath(); + String leftHqlPath = getHqlDataInstance().getHqlPath(); if (filter.getRightSidePath() != null) { if (!(filter instanceof EqualFilter)) { throw new QueryException("Right-side ItemPath is supported currently only for EqualFilter, not for " + filter); } - ItemPathResolutionState rightItemState = getItemPathResolver().resolveRightItemPath( - getItemPathResolutionStateForChildren(), filter.getRightSidePath()); - String rightHqlPath = rightItemState.getCurrentHqlPath(); + HqlDataInstance rightItem = getItemPathResolver().resolveItemPath(filter.getRightSidePath(), + getBaseHqlEntityForChildren(), true); + String rightHqlPath = rightItem.getHqlPath(); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); // left = right OR (left IS NULL AND right IS NULL) Condition condition = hibernateQuery.createEqXY(leftHqlPath, rightHqlPath, "=", false); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java index 44ad54a13bc..206de4124cf 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ReferenceRestriction.java @@ -58,7 +58,7 @@ public ReferenceRestriction(InterpretationContext context, RefFilter filter, Jpa @Override public Condition interpretInternal() throws QueryException { - String hqlPath = getItemResolutionState().getCurrentHqlPath(); + String hqlPath = getHqlDataInstance().getHqlPath(); LOGGER.trace("interpretInternal starting with hqlPath = {}", hqlPath); List values = filter.getValues(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index d90dbbb57b9..5a5333c1b03 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -16,32 +16,30 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.HqlEntityInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.ItemPathResolver; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import org.apache.commons.lang.Validate; -import org.hibernate.Session; /** - * An image of an ObjectFilter, forming a restriction tree. - * Preserves some state related to the interpretation (translation). - * Provides functionality related to the translation. + * An image of an ObjectFilter, forming a restriction tree. + * Preserves some state related to the interpretation (translation). + * Provides functionality related to the translation. * - * As for the state, we maintain (or, more precisely, we are able to determine) the following: - * - base ItemPath for the restriction - * - base HQL property path for the restriction - * - base EntityDefinition for the restriction - * (plus, as a convenience method, the same for children of this restriction) + * As for the state, we maintain (or, more precisely, we are able to determine) the following: + * - base HQL property path for the restriction + * - base EntityDefinition for the restriction + * - chain of translation states that led to the starting HQL property path (if applicable) + * This is stored in baseHqlEntity. * * Most restrictions do not change the above properties when propagating them to their children. * However, Type and Exists restrictions do. - * The former changes EntityDefinition, the latter all the three. + * The former changes EntityDefinition, the latter all three. * * Also, item-related restrictions may, at their own discretion, use an EntityDefinition that * points to a subclass of the one provided by the parent restriction. They do that if the item @@ -57,18 +55,36 @@ */ public abstract class Restriction { - protected InterpretationContext context; - protected Restriction parent; - protected T filter; + final protected InterpretationContext context; + final protected Restriction parent; + final protected T filter; /** - * Entity definition to be used as "root" by this restriction and its children. + * Content of ItemPathResolutionStartInformation: + * + * (1) Entity definition to be used as "root" by this restriction and its children. * * Looks a bit weird, but entity definition is provided to the restriction by the caller (query interpreter). * Actually, the caller has to determine it, because it needs it to know what restriction to instantiate. - * (TODO reconsider this) + * + * (2) HQL property path of the object to which this restriction is to be applied. + * + * Usually, e.g. for simple cases like UserType: name, UserType: activation/administrativeStatus etc. the root + * is the query primary entity alias (e.g. u in "RUser u"). + * + * For "Exists" filters children the base corresponds to the base item pointed to by the filter. + * E.g. + * - in "UserType: Exists (assignment)" it is "a" (provided that there is + * "RUser u left join u.assignments a with ..." already defined). + * - in "UserType: Exists (assignment/activation)" it is "a.activation" + * [although note that using single-valued properties as last path item + * in "Exists" filter is only a syntactic sugar] + * + * (3) List of translation steps that had led to the HQL property path. Useful for following ".." + * segments in item paths. + * */ - protected JpaEntityDefinition baseEntityDefinition; + final protected HqlEntityInstance baseHqlEntity; public Restriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { Validate.notNull(context, "context"); @@ -77,35 +93,27 @@ public Restriction(InterpretationContext context, T filter, JpaEntityDefinition this.context = context; this.filter = filter; this.parent = parent; - this.baseEntityDefinition = baseEntityDefinition; + if (parent != null) { + baseHqlEntity = parent.getBaseHqlEntityForChildren().narrowFor(baseEntityDefinition); + } else { + baseHqlEntity = new HqlEntityInstance(context.getPrimaryEntityAlias(), baseEntityDefinition, null); + } } public T getFilter() { return filter; } - public void setFilter(T filter) { - this.filter = filter; - } - public InterpretationContext getContext() { return context; } - public void setContext(InterpretationContext context) { - this.context = context; - } - - public Session getSession() { - return context.getSession(); - } - public Restriction getParent() { return parent; } - public void setParent(Restriction parent) { - this.parent = parent; + public HqlEntityInstance getBaseHqlEntity() { + return baseHqlEntity; } public abstract Condition interpret() throws QueryException; @@ -118,105 +126,12 @@ protected String nameOf(Enum e) { return e.getClass().getName() + "." + e.name(); } - /** - * HQL property path of the object to which this restriction is to be applied. - * - * Usually, e.g. for simple cases like UserType: name, UserType: activation/administrativeStatus etc. the root - * is the query primary entity alias (e.g. u in "RUser u"). - * - * For "Exists" filters children the base corresponds to the base item pointed to by the filter. - * E.g. - * - in "UserType: Exists (assignment)" it is "a" (provided that there is - * "RUser u left join u.assignments a with ..." already defined). - * - in "UserType: Exists (assignment/activation)" it is "a.activation" - * [although note that using single-valued properties as last path item - * in "Exists" filter is only a syntactic sugar] - */ - public String getBaseHqlPath() { - if (parent == null) { - return context.getHibernateQuery().getPrimaryEntityAlias(); - } else { - return parent.getBaseHqlPathForChildren(); - } - } - - /** - * HQL property path for children of this restriction. - * By default it is the same as base path for this one; however subclasses (namely Exists) may change that. - */ - public String getBaseHqlPathForChildren() { - return getBaseHqlPath(); - } - - public ItemPath getBaseItemPath() { - if (parent == null) { - return ItemPath.EMPTY_PATH; - } else { - return parent.getBaseItemPathForChildren(); - } - } - - /** - * Returns the item path that is the "base" path for any child restrictions. - * Default is the empty path. - * - * Currently, only the ForValue filter/restriction changes this path. E.g. for UserType: ForValue (assignment) - * changes the base path for its children to "assignment". - */ - public ItemPath getBaseItemPathForChildren() { - return getBaseItemPath(); - } - - /** - * Given the (relative) path, returns full path of an item to be used in a restriction. - * - * @param path - * @return - */ - protected ItemPath getFullPath(ItemPath path) { - return new ItemPath(parent.getBaseItemPath(), path); - } - - public JpaEntityDefinition getBaseEntityDefinition() { - return baseEntityDefinition; - } - - public JpaEntityDefinition getBaseEntityDefinitionForChildren() { - return getBaseEntityDefinition(); - } - - // temporary hack - TODO implement more seriously - public ItemPathResolutionState getItemPathResolutionStateForChildren() { - if (parent != null) { - return parent.getItemPathResolutionStateForChildren(); - } else { - return new ItemPathResolutionState( - ItemPath.EMPTY_PATH, // this is dummy - getBaseHqlPath(), - getBaseEntityDefinition(), - getItemPathResolver() - ); - } + public HqlEntityInstance getBaseHqlEntityForChildren() { + return getBaseHqlEntity(); } protected ItemPathResolver getItemPathResolver() { return getContext().getItemPathResolver(); } -// /** -// * Finds TypeFilter that is applicable in a current context. -// * Simple algorithm is to check all the parents. -// * More complex one (not yet implemented) would be to check also sibling restrictions in an AndRestriction, if -// * there's any. -// * -// * @return -// */ -// public TypeFilter findApplicableTypeFilter() { -// if (parent != null) { -// return parent.findApplicableTypeFilter(); -// } else { -// return null; -// } -// } - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java index 7345fbe2318..ff07339862a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/TypeRestriction.java @@ -46,7 +46,7 @@ public Condition interpret() throws QueryException { InterpretationContext context = getContext(); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - String property = getBaseHqlPath() + "." + RObject.F_OBJECT_TYPE_CLASS; + String property = getBaseHqlEntity().getHqlPath() + "." + RObject.F_OBJECT_TYPE_CLASS; Set values = getValues(filter.getType()); From c6d875e4e1aa66e4ce32f31b958fd35c77567174 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 2 Dec 2015 11:27:55 +0100 Subject: [PATCH 054/116] Aligned processing of "any" properties with standard ones, enabling them to take part in item-item comparisons. Implemented item-item comparisons for ComparativeFilters. --- .../midpoint/prism/path/ItemPath.java | 12 +++ .../midpoint/prism/query/EqualFilter.java | 13 ++- .../prism/query/PropertyValueFilter.java | 21 ++++- .../repo/sql/QueryInterpreter2Test.java | 28 ++++++- .../sql/query2/InterpretationContext.java | 1 + .../repo/sql/query2/QueryInterpreter2.java | 47 ++++++----- .../definition/ClassDefinitionParser.java | 4 +- .../sql/query2/definition/DefinitionPath.java | 81 ------------------ .../definition/JpaAnyContainerDefinition.java | 84 +++++++++++++++++++ ...ion.java => JpaAnyPropertyDefinition.java} | 36 +++----- .../JpaAnyPropertyLinkDefinition.java | 45 ++++++++++ .../definition/JpaDataNodeDefinition.java | 9 +- .../definition/JpaEntityDefinition.java | 59 ++++--------- .../JpaEntityPointerDefinition.java | 7 +- .../definition/JpaPropertyDefinition.java | 7 +- .../definition/JpaReferenceDefinition.java | 5 +- .../definition/LinkDefinitionComparator.java | 2 +- ...ava => VirtualAnyContainerDefinition.java} | 4 +- .../sql/query2/hqm/RootHibernateQuery.java | 2 +- .../repo/sql/query2/matcher/Matcher.java | 8 +- .../{ => resolution}/DataSearchResult.java | 2 +- .../{ => resolution}/HqlDataInstance.java | 18 ++-- .../{ => resolution}/HqlEntityInstance.java | 2 +- .../ItemPathResolutionState.java | 11 +-- .../{ => resolution}/ItemPathResolver.java | 53 ++++++++---- .../ProperDataSearchResult.java | 2 +- .../restriction/AnyPropertyRestriction.java | 71 +++------------- .../query2/restriction/ExistsRestriction.java | 13 ++- .../query2/restriction/ItemRestriction.java | 14 +++- .../restriction/ItemRestrictionOperation.java | 15 +++- .../restriction/ItemValueRestriction.java | 52 ++++++------ .../restriction/PropertyRestriction.java | 56 ++++++++----- .../sql/query2/restriction/Restriction.java | 4 +- 33 files changed, 431 insertions(+), 357 deletions(-) delete mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyContainerDefinition.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{JpaAnyDefinition.java => JpaAnyPropertyDefinition.java} (52%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyLinkDefinition.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/{VirtualAnyDefinition.java => VirtualAnyContainerDefinition.java} (90%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ => resolution}/DataSearchResult.java (96%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ => resolution}/HqlDataInstance.java (82%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ => resolution}/HqlEntityInstance.java (96%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ => resolution}/ItemPathResolutionState.java (94%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ => resolution}/ItemPathResolver.java (76%) rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/{ => resolution}/ProperDataSearchResult.java (96%) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index b2d3f8f6c46..7f264f6e3e1 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -360,6 +360,18 @@ public boolean startsWith(Class clazz) { } } + public QName asSingleName() { + if (size() == 1 && startsWith(NameItemPathSegment.class)) { + return ((NameItemPathSegment) first()).getName(); + } else { + return null; + } + } + + public static QName asSingleName(ItemPath path) { + return path != null ? path.asSingleName() : null; + } + public enum CompareResult { EQUIVALENT, SUPERPATH, diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java index b8e8e238490..fee95ef50f8 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java @@ -20,6 +20,7 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.match.MatchingRule; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; @@ -52,8 +53,8 @@ public class EqualFilter extends PropertyValueFilter definition, QName matchingRule, ItemPath rightSidePath) { - super(parentPath, definition, matchingRule, rightSidePath); + EqualFilter(ItemPath parentPath, PrismPropertyDefinition definition, QName matchingRule, ItemPath rightSidePath, ItemDefinition rightSideDefinition) { + super(parentPath, definition, matchingRule, rightSidePath, rightSideDefinition); } private EqualFilter(ItemPath parentPath, PrismPropertyDefinition definition, QName matchingRule) { @@ -157,7 +158,13 @@ public static EqualFilter createEqual(ItemPath p public static EqualFilter createEqual(ItemPath propertyPath, Class type, PrismContext prismContext, QName matchingRule, ItemPath rightSidePath) { PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(propertyPath, type, prismContext); - EqualFilter filter = new EqualFilter(propertyPath, propertyDefinition, matchingRule, rightSidePath); + EqualFilter filter = new EqualFilter(propertyPath, propertyDefinition, matchingRule, rightSidePath, null); + return filter; + } + + public static EqualFilter createEqual(ItemPath propertyPath, Class type, PrismContext prismContext, QName matchingRule, ItemPath rightSidePath, ItemDefinition rightSideDefinition) { + PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) FilterUtils.findItemDefinition(propertyPath, type, prismContext); + EqualFilter filter = new EqualFilter(propertyPath, propertyDefinition, matchingRule, rightSidePath, rightSideDefinition); return filter; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java index 42d7eb92243..a0f1b9a5885 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java @@ -57,15 +57,18 @@ public abstract class PropertyValueFilter extends ValueFil private ExpressionWrapper expression; private List values; - private ItemPath rightSidePath; + private ItemPath rightSidePath; // alternative to "values" + private ItemDefinition rightSideDefinition; // optional (needed only if path points to extension item) PropertyValueFilter() { super(); } - PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, ItemPath rightSidePath) { + PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, ItemPath rightSidePath, ItemDefinition rightSideDefinition) { super(path, definition, matchingRule); + Validate.notNull(rightSidePath, "rightSidePath"); this.rightSidePath = rightSidePath; + this.rightSideDefinition = rightSideDefinition; } PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, List values) { @@ -145,6 +148,16 @@ static List> createPropertyList(PrismPropertyDefinitio public List getValues() { return values; } + + public T getSingleValue() { + if (values == null) { + return null; + } + if (values.size() > 1) { + throw new IllegalArgumentException("Filter '" + this + "' should contain at most one value, but it has " + values.size() + " of them."); + } + return values.iterator().next(); + } public void setValues(List values) { this.values = values; @@ -201,6 +214,10 @@ public ItemPath getRightSidePath() { return rightSidePath; } + public ItemDefinition getRightSideDefinition() { + return rightSideDefinition; + } + public ExpressionWrapper getExpression() { return expression; } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 4e25a1d134c..e7b29a5c6b3 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -2710,7 +2710,8 @@ public void test820OrderByTargetName() throws Exception { } } - @Test(expectedExceptions = Exception.class) // should fail, as Equals supports single-value right side only + @Test(expectedExceptions = IllegalArgumentException.class) // should fail, as Equals supports single-value right side only + // TODO this should be perhaps checked in EqualFilter public void test900EqualsMultivalue() throws Exception { Session session = open(); @@ -2779,7 +2780,7 @@ public void test910PreferredLanguageEqualsCostCenter() throws Exception { } } - @Test(enabled = false) + @Test(enabled = false) // different types of properties that are to be compared (polystring vs string in this case) are not supported yet public void test915OrganizationEqualsCostCenter() throws Exception { Session session = open(); @@ -2871,6 +2872,29 @@ public void test920DecisionsNotAnswered() throws Exception { } } +// @Test +// public void test930OrganizationEqualsCostCenter() throws Exception { +// Session session = open(); +// +// try { +// /* +// * ### User: organization = costCenter +// */ +// ObjectQuery query = ObjectQuery.createObjectQuery( +// EqualFilter.createEqual( +// new ItemPath(UserType.F_ORGANIZATION), +// UserType.class, +// prismContext, +// null, +// new ItemPath(UserType.F_COST_CENTER))); +// +// String real = getInterpretedQuery2(session, UserType.class, query); +//// assertEqualsIgnoreWhitespace(expected, real); +// } finally { +// close(session); +// } +// } + // TODO negative tests - order by entity, reference, any, collection // TODO implement checks for "order by" for non-singletons diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java index 68133ee7323..e63dc00b352 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/InterpretationContext.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.resolution.ItemPathResolver; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index a87dfb25a2a..e550f2a56fe 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.query2; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; @@ -36,11 +37,11 @@ import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.prism.query.UndefinedFilter; -import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyContainerDefinition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaReferenceDefinition; @@ -52,6 +53,8 @@ import com.evolveum.midpoint.repo.sql.query2.matcher.Matcher; import com.evolveum.midpoint.repo.sql.query2.matcher.PolyStringMatcher; import com.evolveum.midpoint.repo.sql.query2.matcher.StringMatcher; +import com.evolveum.midpoint.repo.sql.query2.resolution.ItemPathResolver; +import com.evolveum.midpoint.repo.sql.query2.resolution.ProperDataSearchResult; import com.evolveum.midpoint.repo.sql.query2.restriction.AndRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.AnyPropertyRestriction; import com.evolveum.midpoint.repo.sql.query2.restriction.ExistsRestriction; @@ -206,7 +209,7 @@ private Restriction findAndCreateRestriction(T filter, private Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext context, Restriction parent, - ItemPathResolver helper, JpaEntityDefinition baseEntityDefinition) throws QueryException { + ItemPathResolver resolver, JpaEntityDefinition baseEntityDefinition) throws QueryException { // the order of processing restrictions can be important, so we do the selection via handwritten code @@ -222,12 +225,14 @@ Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext con return new OrgRestriction(context, (OrgFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof TypeFilter) { TypeFilter typeFilter = (TypeFilter) filter; - JpaEntityDefinition refinedEntityDefinition = helper.findRestrictedEntityDefinition(baseEntityDefinition, typeFilter.getType()); + JpaEntityDefinition refinedEntityDefinition = resolver.findRestrictedEntityDefinition(baseEntityDefinition, typeFilter.getType()); return new TypeRestriction(context, typeFilter, refinedEntityDefinition, parent); } else if (filter instanceof ExistsFilter) { ExistsFilter existsFilter = (ExistsFilter) filter; ItemPath path = existsFilter.getFullPath(); - ProperDataSearchResult searchResult = helper.findProperDataDefinition(baseEntityDefinition, path, JpaEntityDefinition.class); + ItemDefinition definition = existsFilter.getDefinition(); + ProperDataSearchResult searchResult = resolver.findProperDataDefinition( + baseEntityDefinition, path, definition, JpaEntityDefinition.class); if (searchResult == null) { throw new QueryException("Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity within " + baseEntityDefinition); } @@ -235,7 +240,9 @@ Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext con } else if (filter instanceof RefFilter) { RefFilter refFilter = (RefFilter) filter; ItemPath path = refFilter.getFullPath(); - ProperDataSearchResult searchResult = helper.findProperDataDefinition(baseEntityDefinition, path, JpaReferenceDefinition.class); + ItemDefinition definition = refFilter.getDefinition(); + ProperDataSearchResult searchResult = resolver.findProperDataDefinition( + baseEntityDefinition, path, definition, JpaReferenceDefinition.class); if (searchResult == null) { throw new QueryException("Path for RefFilter (" + path + ") doesn't point to a reference item within " + baseEntityDefinition); } @@ -244,21 +251,18 @@ Restriction findAndCreateRestrictionInternal(T filter, InterpretationContext con } else if (filter instanceof PropertyValueFilter) { PropertyValueFilter valFilter = (PropertyValueFilter) filter; ItemPath path = valFilter.getFullPath(); + ItemDefinition definition = valFilter.getDefinition(); - ProperDataSearchResult propDefRes = helper.findProperDataDefinition(baseEntityDefinition, path, JpaPropertyDefinition.class); - if (propDefRes != null) { - return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getLinkDefinition()); + ProperDataSearchResult propDefRes = resolver.findProperDataDefinition(baseEntityDefinition, path, definition, JpaPropertyDefinition.class); + if (propDefRes == null) { + throw new QueryException("Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); } - ProperDataSearchResult anyDefRes = helper.findProperDataDefinition(baseEntityDefinition, path, JpaAnyDefinition.class); - if (anyDefRes != null) { - if (ItemPath.containsSingleNameSegment(anyDefRes.getRemainder())) { - return new AnyPropertyRestriction(context, valFilter, anyDefRes.getEntityDefinition(), parent, anyDefRes.getTargetDefinition()); - } else { - throw new QueryException("Unsupported any-targeted query: should contain single item name to be resolved in the 'any' container but contains '" + - anyDefRes.getRemainder() + "' instead"); - } + // TODO can't be unified? + if (propDefRes.getTargetDefinition() instanceof JpaAnyPropertyDefinition) { + return new AnyPropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getLinkDefinition()); + } else { + return new PropertyRestriction(context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getLinkDefinition()); } - throw new QueryException("Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); } else if (filter instanceof NoneFilter || filter instanceof AllFilter || filter instanceof UndefinedFilter) { // these should be filtered out by the client throw new IllegalStateException("Trivial filters are not supported by QueryInterpreter: " + filter.debugDump()); @@ -320,14 +324,15 @@ public void updatePagingAndSorting(InterpretationConte } } + // TODO if we'd like to have order-by extension properties, we'd need to provide itemDefinition for them ProperDataSearchResult result = context.getItemPathResolver().findProperDataDefinition( - context.getRootEntityDefinition(), orderByPath, JpaDataNodeDefinition.class); + context.getRootEntityDefinition(), orderByPath, null, JpaDataNodeDefinition.class); if (result == null) { throw new QueryException("Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it."); } JpaDataNodeDefinition targetDefinition = result.getLinkDefinition().getTargetDefinition(); - if (targetDefinition instanceof JpaAnyDefinition) { + if (targetDefinition instanceof JpaAnyContainerDefinition) { throw new QueryException("Sorting based on extension item or attribute is not supported yet: " + orderByPath); } else if (targetDefinition instanceof JpaReferenceDefinition) { throw new QueryException("Sorting based on reference is not supported: " + orderByPath); @@ -342,7 +347,7 @@ public void updatePagingAndSorting(InterpretationConte JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition(); JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) targetDefinition; String hqlPropertyPath = context.getItemPathResolver() - .resolveItemPath(orderByPath, context.getPrimaryEntityAlias(), baseEntityDefinition, true) + .resolveItemPath(orderByPath, null, context.getPrimaryEntityAlias(), baseEntityDefinition, true) .getHqlPath(); if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index b03f74355cf..769a6ca4c54 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -130,7 +130,7 @@ private JpaLinkDefinition parseMethod(Method method) { JpaLinkDefinition linkDefinition; Any any = method.getAnnotation(Any.class); if (any != null) { - JpaAnyDefinition targetDefinition = new JpaAnyDefinition(jpaClass); + JpaAnyContainerDefinition targetDefinition = new JpaAnyContainerDefinition(jpaClass); QName jaxbNameForAny = new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()); linkDefinition = new JpaLinkDefinition<>(jaxbNameForAny, jpaName, collectionSpecification, false, targetDefinition); } else if (ObjectReference.class.isAssignableFrom(jpaClass)) { @@ -188,7 +188,7 @@ private void addVirtualDefinitionsForClass(Class jpaClass, JpaEntityDefinition e for (VirtualAny any : qEntity.anyElements()) { QName jaxbName = new QName(any.jaxbNameNamespace(), any.jaxbNameLocalPart()); - VirtualAnyDefinition def = new VirtualAnyDefinition(any.ownerType()); + VirtualAnyContainerDefinition def = new VirtualAnyContainerDefinition(any.ownerType()); JpaLinkDefinition linkDefinition = new JpaLinkDefinition(jaxbName, null, null, false, def); entityDef.addDefinition(linkDefinition); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java deleted file mode 100644 index 971c00a22ab..00000000000 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/DefinitionPath.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.repo.sql.query2.definition; - -import java.util.ArrayList; -import java.util.List; - -/** - * A path of JPA definitions. Analogous to ItemPath; however, expresses the path in JPA terms, not prism terms. - * Auxiliary definitions (e.g. real EntityDefinition referenced by EntityReferenceDefinition) are NOT in such - * paths. I.e. path corresponds to the path of JPA (hibernate) names. - * - * Example: - * - * base entity = RUser - * prism path = assignment/target/link/activation/administrativeStatus (i.e. looks for admin status of a projection of e.g. assigned role) - * def path = - * Ent: assignment (RAssignment) - * Ref: target (real entity = RObject) - * Ref: link (real entity = RObject) - * Ent: activation - * Prop: administrativeStatus - * - * @author mederly - */ -public class DefinitionPath { - - private List definitions = new ArrayList<>(); - - public void add(JpaLinkDefinition definition) { - definitions.add(definition); - } - - public List getDefinitions() { - return definitions; - } - - public int size() { - return definitions.size(); - } - - public JpaLinkDefinition get(int i) { - return definitions.get(i); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - boolean first = true; - - for (JpaLinkDefinition definition : definitions) { - if (first) { - first = false; - } else { - sb.append(", "); - } - if (definition != null) { - sb.append(definition); - } else { - sb.append("null"); // Just to catch errors in translations - } - } - sb.append(']'); - return sb.toString(); - } -} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyContainerDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyContainerDefinition.java new file mode 100644 index 00000000000..349bd06ba9f --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyContainerDefinition.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyConverter; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; + +/** + * @author lazyman + */ +public class JpaAnyContainerDefinition extends JpaDataNodeDefinition { + + public JpaAnyContainerDefinition(Class jpaClass) { + super(jpaClass, null); + } + + @Override + protected String getDebugDumpClassName() { + return "Any"; + } + + @Override + public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition) throws QueryException { + QName itemName = ItemPath.asSingleName(path); + if (itemName == null) { + throw new QueryException("Couldn't resolve paths other than those in the form of single name in extension/attributes container: " + path); + } + if (itemDefinition == null) { + throw new QueryException("Couldn't resolve dynamically defined item path '" + path + "' without proper definition"); + } + + String jpaName; // longs, strings, ... + try { + jpaName = RAnyConverter.getAnySetType(itemDefinition); + } catch (SchemaException e) { + throw new QueryException(e.getMessage(), e); + } + + RObjectExtensionType ownerType = getOwnerType(); + + CollectionSpecification collSpec = itemDefinition.isSingleValue() ? null : new CollectionSpecification(); + JpaAnyPropertyDefinition anyPropDefinition = new JpaAnyPropertyDefinition(Object.class, null); // TODO + JpaLinkDefinition linkDefinition = new JpaAnyPropertyLinkDefinition(itemName, jpaName, collSpec, ownerType, anyPropDefinition); + DataSearchResult result = new DataSearchResult(linkDefinition, ItemPath.EMPTY_PATH); + return result; + } + + // assignment extension has no ownerType, but virtual (object extension / shadow attributes) do have + protected RObjectExtensionType getOwnerType() { + return null; + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } + + @Override + public String debugDump(int indent) { + return super.getShortInfo(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyDefinition.java similarity index 52% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyDefinition.java index 4bcef663355..c36e74967a6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyDefinition.java @@ -16,36 +16,24 @@ package com.evolveum.midpoint.repo.sql.query2.definition; -import com.evolveum.midpoint.prism.Visitor; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; - /** - * @author lazyman + * Specifies "any" property. In contrast to other JPA definitions, it is not derived by analyzing R-class + * structure, but created on demand in the process if ItemPath translation. + * + * It was created to ensure consistency of resolution mechanism, which should provide + * HQL property + JPA definition for any item path provided. + * + * @author mederly */ -public class JpaAnyDefinition extends JpaDataNodeDefinition { +public class JpaAnyPropertyDefinition extends JpaPropertyDefinition { - public JpaAnyDefinition(Class jpaClass) { - super(jpaClass, null); + // enumerated extension items are not supported + public JpaAnyPropertyDefinition(Class jpaClass, Class jaxbClass) { + super(jpaClass, jaxbClass, false, false, false); } @Override protected String getDebugDumpClassName() { - return "Any"; - } - - @Override - public DataSearchResult nextLinkDefinition(ItemPath path) { - throw new UnsupportedOperationException(); // TODO - } - - @Override - public void accept(Visitor visitor) { - visitor.visit(this); - } - - @Override - public String debugDump(int indent) { - return super.getShortInfo(); + return "AnyProperty"; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyLinkDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyLinkDefinition.java new file mode 100644 index 00000000000..90c713e085d --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaAnyPropertyLinkDefinition.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import com.evolveum.midpoint.prism.path.NameItemPathSegment; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; + +import javax.xml.namespace.QName; + +/** + * Link from AnyContainer to specific item in this container. + * + * @author mederly + */ +public class JpaAnyPropertyLinkDefinition extends JpaLinkDefinition { + + final private RObjectExtensionType ownerType; + + public JpaAnyPropertyLinkDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, RObjectExtensionType ownerType, JpaDataNodeDefinition targetDefinition) { + super(jaxbName, jpaName, collectionSpecification, false, targetDefinition); + this.ownerType = ownerType; + } + + public RObjectExtensionType getOwnerType() { + return ownerType; + } + + public QName getItemName() { + return ((NameItemPathSegment) getItemPathSegment()).getName(); + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java index 8e8020cc8ad..927d9b9c7d0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java @@ -16,17 +16,16 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import org.apache.commons.lang.Validate; -import javax.xml.namespace.QName; - /** * Defines piece of JPA data - entity, property, reference, or "any" container. Used to convert ItemPath to HQL query, * or, specifically, to a property path with left outer joins where appropriate. @@ -88,14 +87,14 @@ public Class getJaxbClass() { * Tries to find "next step" in the translation process for a given ItemPath. * * @param path A path to be resolved. Always non-null and non-empty. Should produce at least one transition. + * @param itemDefinition Item definition for the item being sought. Needed only for "any" items. * @return * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain * and the unresolved remainder of the path. The transition may be empty ("self") e.g. for metadata or construction. * - If the search was not successful, returns null. * - * Method is not supported on AnyDefinition! */ - public abstract DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException; + public abstract DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition) throws QueryException; public String toString() { return getShortInfo(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java index a0e1701d28f..fa0a3ab19c0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java @@ -16,26 +16,20 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathSegment; -import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; -import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import org.apache.commons.lang.Validate; -import javax.xml.namespace.QName; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; @@ -91,24 +85,24 @@ public interface LinkDefinitionHandler { } /** - * Resolves the whole ItemPath (non-empty!) + * Resolves the whole ItemPath * - * If successful, returns either: - * - correct definition + empty path, or - * - Any definition + path remainder + * @param path ItemPath to resolve. Non-empty! + * @param itemDefinition Definition of the final path segment, if it's "any" property. + * @param type Type of definition to be found + * @return * + * If successful, returns correct definition + empty path. * If unsuccessful, return null. - * - * @return */ - public DataSearchResult findDataNodeDefinition(ItemPath path, Class type) throws QueryException { - return findDataNodeDefinition(path, type, null); + public DataSearchResult findDataNodeDefinition(ItemPath path, ItemDefinition itemDefinition, Class type) throws QueryException { + return findDataNodeDefinition(path, itemDefinition, type, null); } - public DataSearchResult findDataNodeDefinition(ItemPath path, Class type, LinkDefinitionHandler handler) throws QueryException { + public DataSearchResult findDataNodeDefinition(ItemPath path, ItemDefinition itemDefinition, Class type, LinkDefinitionHandler handler) throws QueryException { JpaDataNodeDefinition currentDefinition = this; for (;;) { - DataSearchResult result = currentDefinition.nextLinkDefinition(path); + DataSearchResult result = currentDefinition.nextLinkDefinition(path, itemDefinition); if (result == null) { // oops return null; } @@ -118,7 +112,7 @@ public DataSearchResult findDataNodeDefinit JpaLinkDefinition linkDefinition = result.getLinkDefinition(); JpaDataNodeDefinition targetDefinition = linkDefinition.getTargetDefinition(); - if (result.isComplete() || targetDefinition instanceof JpaAnyDefinition) { + if (result.isComplete()) { if (type.isAssignableFrom(targetDefinition.getClass())) { return (DataSearchResult) result; } else { @@ -131,31 +125,6 @@ public DataSearchResult findDataNodeDefinit } } - /** - * Translates ItemPath to a sequence of definitions. - * - * @param itemPath - * @return The translation (if successful) or null (if not successful). - * For "Any" elements, the last element in the path is Any. - */ - - public DefinitionPath translatePath(ItemPath itemPath) throws QueryException { - final DefinitionPath definitionPath = new DefinitionPath(); - DataSearchResult result = findDataNodeDefinition(itemPath, JpaDataNodeDefinition.class, new LinkDefinitionHandler() { - @Override - public void handle(JpaLinkDefinition linkDefinition) { - definitionPath.add(linkDefinition); - } - }); - if (result != null) { - LOGGER.trace("ItemPath {} successfully translated to DefinitionPath {} (started in {})", itemPath, definitionPath, this); - return definitionPath; - } else { - LOGGER.trace("ItemPath {} PARTIALLY translated to DefinitionPath {} (started in {})", itemPath, definitionPath, this); - return null; - } - } - public void setSuperclassDefinition(JpaEntityDefinition superclassDefinition) { this.superclassDefinition = superclassDefinition; } @@ -165,7 +134,7 @@ public JpaEntityDefinition getSuperclassDefinition() { } @Override - public DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException { + public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition) throws QueryException { if (ItemPath.isNullOrEmpty(path)) { // doesn't fulfill precondition return null; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java index 8d083f6b504..36b65745583 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityPointerDefinition.java @@ -16,10 +16,11 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; /** * Special placeholder to allow for cross-references: entity definition that points to another entity. @@ -52,8 +53,8 @@ public void setResolvedEntityDefinition(JpaEntityDefinition resolvedEntityDefini } @Override - public DataSearchResult nextLinkDefinition(ItemPath path) throws QueryException { - return resolvedEntityDefinition.nextLinkDefinition(path); + public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition) throws QueryException { + return resolvedEntityDefinition.nextLinkDefinition(path, itemDefinition); } @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java index 17383f86f5f..d8d34a29fd4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaPropertyDefinition.java @@ -16,10 +16,11 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; -import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; /** * @author lazyman @@ -30,7 +31,7 @@ public class JpaPropertyDefinition extends JpaDataNodeDefinition { private boolean lob; private boolean enumerated; //jpa special things - private boolean indexed; + private boolean indexed; // currently unused public JpaPropertyDefinition(Class jpaClass, Class jaxbClass, boolean lob, boolean enumerated, boolean indexed) { super(jpaClass, jaxbClass); @@ -73,7 +74,7 @@ protected String getDebugDumpClassName() { } @Override - public DataSearchResult nextLinkDefinition(ItemPath path) { + public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition) { // nowhere to come from here return null; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java index 7d09e79dd95..1674de70f70 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaReferenceDefinition.java @@ -16,10 +16,11 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Visitor; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ObjectReferencePathSegment; -import com.evolveum.midpoint.repo.sql.query2.DataSearchResult; +import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; import org.apache.commons.lang.Validate; /** @@ -41,7 +42,7 @@ protected String getDebugDumpClassName() { } @Override - public DataSearchResult nextLinkDefinition(ItemPath path) { + public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition) { if (path.first() instanceof ObjectReferencePathSegment) { // returning artificially created transition definition, used to allow dereferencing target object in a generic way return new DataSearchResult( diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java index 7eb3a1be358..6c6eb91b6d6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java @@ -44,7 +44,7 @@ private int getType(JpaDataNodeDefinition def) { return 1; } else if (def instanceof JpaReferenceDefinition) { return 2; - } else if (def instanceof JpaAnyDefinition) { + } else if (def instanceof JpaAnyContainerDefinition) { return 4; } else if (def instanceof JpaEntityDefinition) { return 5; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyContainerDefinition.java similarity index 90% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyContainerDefinition.java index 9388e22591b..d7180ae33fa 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/VirtualAnyContainerDefinition.java @@ -23,11 +23,11 @@ /** * @author mederly */ -public class VirtualAnyDefinition extends JpaAnyDefinition { +public class VirtualAnyContainerDefinition extends JpaAnyContainerDefinition { private RObjectExtensionType ownerType; // ObjectType (for extension) or ShadowType (for attributes) - public VirtualAnyDefinition(RObjectExtensionType ownerType) { + public VirtualAnyContainerDefinition(RObjectExtensionType ownerType) { super(RObject.class); // RObject is artificial - don't want to make jpaClass nullable just for this single situation Validate.notNull(ownerType, "ownerType"); this.ownerType = ownerType; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java index fa35b054519..db5314150d5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/RootHibernateQuery.java @@ -186,7 +186,7 @@ public Condition createIn(String propertyPath, String subqueryText) { return new InCondition(this, propertyPath, subqueryText); } - public Condition createEqXY(String leftSidePropertyPath, String rightSidePropertyPath, String operator, boolean ignoreCase) { + public Condition createCompareXY(String leftSidePropertyPath, String rightSidePropertyPath, String operator, boolean ignoreCase) { return new PropertyPropertyComparisonCondition(this, leftSidePropertyPath, rightSidePropertyPath, operator, ignoreCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java index d9feb98c706..3044e484e39 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/matcher/Matcher.java @@ -68,16 +68,10 @@ protected Condition basicMatch(RootHibernateQuery hibernateQuery, ItemRestrictio } break; case GT: - condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, ">", ignoreCase); - break; case GE: - condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, ">=", ignoreCase); - break; case LT: - condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, "<", ignoreCase); - break; case LE: - condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, "<=", ignoreCase); + condition = hibernateQuery.createSimpleComparisonCondition(propertyPath, value, operation.symbol(), ignoreCase); break; case NOT_NULL: condition = hibernateQuery.createIsNotNull(propertyPath); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DataSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/DataSearchResult.java similarity index 96% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DataSearchResult.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/DataSearchResult.java index b62ce024160..2b1f28bca83 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/DataSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/DataSearchResult.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2; +package com.evolveum.midpoint.repo.sql.query2.resolution; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/HqlDataInstance.java similarity index 82% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/HqlDataInstance.java index b84ef997679..c05315a46dd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlDataInstance.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/HqlDataInstance.java @@ -14,8 +14,10 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2; +package com.evolveum.midpoint.repo.sql.query2.resolution; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.util.DebugDumpable; @@ -40,9 +42,9 @@ public class HqlDataInstance implements DebugDu private static final Trace LOGGER = TraceManager.getTrace(HqlDataInstance.class); - final protected String hqlPath; - final protected D jpaDefinition; - final protected HqlDataInstance parentDataItem; // optional + final protected String hqlPath; // concrete path for accessing this item + final protected D jpaDefinition; // definition of this item + final protected HqlDataInstance parentDataItem; // how we got here - optional public HqlDataInstance(String hqlPath, D jpaDefinition, HqlDataInstance parentDataItem) { @@ -54,7 +56,13 @@ public HqlDataInstance(String hqlPath, D jpaDefinition, } public String getHqlPath() { - return hqlPath; + if (jpaDefinition instanceof JpaAnyPropertyDefinition) { + // This is quite dangerous. Assumes that we don't continue with resolving ItemPath after finding + // this kind of definition (and that's true). + return hqlPath + "." + RAnyValue.F_VALUE; + } else { + return hqlPath; + } } public D getJpaDefinition() { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/HqlEntityInstance.java similarity index 96% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/HqlEntityInstance.java index ab118eb4fbe..288d2009301 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/HqlEntityInstance.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/HqlEntityInstance.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2; +package com.evolveum.midpoint.repo.sql.query2.resolution; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import org.apache.commons.lang.Validate; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolutionState.java similarity index 94% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolutionState.java index 3f5fdc9a374..b461658ada6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolutionState.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolutionState.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2; +package com.evolveum.midpoint.repo.sql.query2.resolution; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.util.DebugDumpable; @@ -76,7 +76,7 @@ public ItemPathResolver getItemPathResolver() { } public boolean isFinal() { - return ItemPath.isNullOrEmpty(remainingItemPath) || hqlDataInstance.getJpaDefinition() instanceof JpaAnyDefinition; + return ItemPath.isNullOrEmpty(remainingItemPath); } /** @@ -85,10 +85,11 @@ public boolean isFinal() { * Precondition: !isFinal() * Precondition: adequate transition exists * + * @param itemDefinition Target item definition (used/required only for "any" properties) * @param singletonOnly Collections are forbidden * @return destination state - always not null */ - public ItemPathResolutionState nextState(boolean singletonOnly) throws QueryException { + public ItemPathResolutionState nextState(ItemDefinition itemDefinition, boolean singletonOnly) throws QueryException { // special case - ".." when having previous state means returning to that state // used e.g. for Exists (some-path, some-conditions AND Equals(../xxx, yyy)) @@ -102,7 +103,7 @@ public ItemPathResolutionState nextState(boolean singletonOnly) throws QueryExce return next; } - DataSearchResult result = hqlDataInstance.getJpaDefinition().nextLinkDefinition(remainingItemPath); + DataSearchResult result = hqlDataInstance.getJpaDefinition().nextLinkDefinition(remainingItemPath, itemDefinition); LOGGER.trace("nextLinkDefinition on '{}' returned '{}'", remainingItemPath, result != null ? result.getLinkDefinition() : "(null)"); if (result == null) { // sorry we failed (however, this should be caught before -> so IllegalStateException) throw new IllegalStateException("Couldn't find " + remainingItemPath + " in " + hqlDataInstance.getJpaDefinition()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java similarity index 76% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java index 578e7178da0..1af14028f4e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ItemPathResolver.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java @@ -14,19 +14,25 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2; +package com.evolveum.midpoint.repo.sql.query2.resolution; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.ParentPathSegment; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query.definition.VirtualQueryParam; +import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; +import com.evolveum.midpoint.repo.sql.query2.QueryDefinitionRegistry2; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyPropertyLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.VirtualCollectionSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; +import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; +import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -53,18 +59,19 @@ public ItemPathResolver(InterpretationContext interpretationContext) { /** * Resolves item path by creating a sequence of resolution states and preparing joins that are used to access JPA properties. - * "singletonOnly" means no collections are allowed (used for right-side path resolution and order criteria). + * @param itemDefinition Definition for the (final) item pointed to. Optional - necessary only for extension items. + * @param singletonOnly Means no collections are allowed (used for right-side path resolution and order criteria). */ - public HqlDataInstance resolveItemPath(ItemPath relativePath, String currentHqlPath, - JpaEntityDefinition baseEntityDefinition, - boolean singletonOnly) throws QueryException { + public HqlDataInstance resolveItemPath(ItemPath relativePath, ItemDefinition itemDefinition, + String currentHqlPath, JpaEntityDefinition baseEntityDefinition, + boolean singletonOnly) throws QueryException { HqlDataInstance baseDataInstance = new HqlDataInstance(currentHqlPath, baseEntityDefinition, null); - return resolveItemPath(relativePath, baseDataInstance, singletonOnly); + return resolveItemPath(relativePath, itemDefinition, baseDataInstance, singletonOnly); } - public HqlDataInstance resolveItemPath(ItemPath relativePath, - HqlDataInstance baseDataInstance, - boolean singletonOnly) throws QueryException { + public HqlDataInstance resolveItemPath(ItemPath relativePath, ItemDefinition itemDefinition, + HqlDataInstance baseDataInstance, + boolean singletonOnly) throws QueryException { ItemPathResolutionState currentState = new ItemPathResolutionState(relativePath, baseDataInstance, this); @@ -72,7 +79,7 @@ public HqlDataInstance resolveItemPath(ItemPath relativePath, while (!currentState.isFinal()) { LOGGER.trace("Current resolution state:\n{}", currentState.debugDumpNoParent()); - currentState = currentState.nextState(singletonOnly); + currentState = currentState.nextState(itemDefinition, singletonOnly); } LOGGER.trace("resolveItemPath({}) ending in resolution state of:\n{}", relativePath, currentState.debugDump()); @@ -85,7 +92,17 @@ String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) th String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); Condition condition = null; - if (joinedItemDefinition.getCollectionSpecification() instanceof VirtualCollectionSpecification) { + if (joinedItemDefinition instanceof JpaAnyPropertyLinkDefinition) { + JpaAnyPropertyLinkDefinition anyLinkDef = (JpaAnyPropertyLinkDefinition) joinedItemDefinition; + AndCondition conjunction = hibernateQuery.createAnd(); + if (anyLinkDef.getOwnerType() != null) { // null for assignment extensions + conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", anyLinkDef.getOwnerType())); + } + conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, + RUtil.qnameToString(anyLinkDef.getItemName()))); + condition = conjunction; + } + else if (joinedItemDefinition.getCollectionSpecification() instanceof VirtualCollectionSpecification) { VirtualCollectionSpecification vcd = (VirtualCollectionSpecification) joinedItemDefinition.getCollectionSpecification(); List conditions = new ArrayList<>(vcd.getAdditionalParams().length); for (VirtualQueryParam vqp : vcd.getAdditionalParams()) { @@ -135,18 +152,20 @@ private Object createQueryParamValue(VirtualQueryParam param) throws QueryExcept * Returns the most abstract entity that can be used. * Checks for conflicts, such as user.locality vs org.locality. * - * @param path Path to be found + * @param path Path to be found (non-empty!) + * @param itemDefinition Definition of target property, required/used only for "any" properties * @param clazz Kind of definition to be looked for * @return Entity type definition + item definition, or null if nothing was found */ public ProperDataSearchResult findProperDataDefinition(JpaEntityDefinition baseEntityDefinition, - ItemPath path, Class clazz) throws QueryException { + ItemPath path, ItemDefinition itemDefinition, + Class clazz) throws QueryException { QueryDefinitionRegistry2 registry = QueryDefinitionRegistry2.getInstance(); ProperDataSearchResult candidateResult = null; for (JpaEntityDefinition entityDefinition : findPossibleBaseEntities(baseEntityDefinition, registry)) { - DataSearchResult result = entityDefinition.findDataNodeDefinition(path, clazz); + DataSearchResult result = entityDefinition.findDataNodeDefinition(path, itemDefinition, clazz); if (result != null) { if (candidateResult == null) { candidateResult = new ProperDataSearchResult<>(entityDefinition, result); @@ -161,8 +180,8 @@ ProperDataSearchResult findProperDataDefinition(JpaEntityDefinition baseEntit } } } - LOGGER.trace("findProperDataDefinition: base='{}', path='{}', class={} -- returning '{}'", - baseEntityDefinition, path, clazz.getSimpleName(), candidateResult); + LOGGER.trace("findProperDataDefinition: base='{}', path='{}', def='{}', class={} -- returning '{}'", + baseEntityDefinition, path, itemDefinition, clazz.getSimpleName(), candidateResult); return candidateResult; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDataSearchResult.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ProperDataSearchResult.java similarity index 96% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDataSearchResult.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ProperDataSearchResult.java index ec3a19f17cd..5a9c2603d87 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/ProperDataSearchResult.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ProperDataSearchResult.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.evolveum.midpoint.repo.sql.query2; +package com.evolveum.midpoint.repo.sql.query2.resolution; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaDataNodeDefinition; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java index b05e217da5a..2ee593c12fb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/AnyPropertyRestriction.java @@ -16,94 +16,43 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.query.PropertyValueFilter; -import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.data.common.any.RAnyConverter; -import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; -import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.definition.JpaAnyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; -import com.evolveum.midpoint.repo.sql.query2.definition.VirtualAnyDefinition; -import com.evolveum.midpoint.repo.sql.query2.hqm.JoinSpecification; -import com.evolveum.midpoint.repo.sql.query2.hqm.RootHibernateQuery; -import com.evolveum.midpoint.repo.sql.query2.hqm.condition.AndCondition; +import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; -import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import org.apache.commons.lang.Validate; - -import javax.xml.namespace.QName; /** * @author lazyman */ -public class AnyPropertyRestriction extends ItemValueRestriction { +public class AnyPropertyRestriction extends PropertyRestriction { private static final Trace LOGGER = TraceManager.getTrace(AnyPropertyRestriction.class); - private JpaAnyDefinition jpaAnyDefinition; public AnyPropertyRestriction(InterpretationContext context, PropertyValueFilter filter, JpaEntityDefinition baseEntityDefinition, - Restriction parent, JpaAnyDefinition jpaAnyDefinition) { - super(context, filter, baseEntityDefinition, parent); - Validate.notNull(jpaAnyDefinition, "anyDefinition"); - this.jpaAnyDefinition = jpaAnyDefinition; + Restriction parent, JpaLinkDefinition jpaLinkDefinition) { + super(context, filter, baseEntityDefinition, parent, jpaLinkDefinition); } @Override public Condition interpretInternal() throws QueryException { - ItemDefinition itemDefinition = filter.getDefinition(); - QName itemName = itemDefinition.getName(); - QName itemType = itemDefinition.getTypeName(); - - if (itemName == null || itemType == null) { - throw new QueryException("Couldn't get name or type for queried item '" + itemDefinition + "'"); - } + String propertyValuePath = getHqlDataInstance().getHqlPath(); - RObjectExtensionType ownerType; - if (jpaAnyDefinition instanceof VirtualAnyDefinition) { - ownerType = ((VirtualAnyDefinition) jpaAnyDefinition).getOwnerType(); + if (filter.getRightSidePath() != null) { + return createPropertyVsPropertyCondition(propertyValuePath); } else { - ownerType = null; // assignment extension has no ownerType + Object value = RAnyConverter.getAggregatedRepoObject(getValue(filter)); + Condition c = createPropertyVsConstantCondition(propertyValuePath, value, filter); + return addIsNotNullIfNecessary(c, propertyValuePath); } - String anyAssociationName; // longs, strings, ... - try { - anyAssociationName = RAnyConverter.getAnySetType(itemDefinition); - } catch (SchemaException e) { - throw new QueryException(e.getMessage(), e); - } - String hqlPath = getHqlDataInstance().getHqlPath(); - String alias = addJoinAny(hqlPath, anyAssociationName, itemName, ownerType); - - String propertyValuePath = alias + '.' + RAnyValue.F_VALUE; - - Object testedValue = getValue(((PropertyValueFilter) filter).getValues()); - Object value = RAnyConverter.getAggregatedRepoObject(testedValue); - Condition c = createCondition(propertyValuePath, value, filter); - - return addIsNotNullIfNecessary(c, propertyValuePath); } - private String addJoinAny(String currentHqlPath, String anyAssociationName, QName itemName, RObjectExtensionType ownerType) { - RootHibernateQuery hibernateQuery = context.getHibernateQuery(); - String joinedItemJpaName = anyAssociationName; - String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemJpaName, false); - AndCondition conjunction = hibernateQuery.createAnd(); - if (ownerType != null) { // null for assignment extensions - conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", ownerType)); - } - conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(itemName))); - - hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, conjunction)); - return joinedItemAlias; - } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java index 47b3e093015..d015c95b729 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ExistsRestriction.java @@ -16,13 +16,11 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ExistsFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; -import com.evolveum.midpoint.repo.sql.query2.HqlEntityInstance; +import com.evolveum.midpoint.repo.sql.query2.resolution.HqlDataInstance; +import com.evolveum.midpoint.repo.sql.query2.resolution.HqlEntityInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; @@ -32,16 +30,15 @@ */ public class ExistsRestriction extends ItemRestriction { - - public ExistsRestriction(InterpretationContext context, ExistsFilter filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { - super(context, filter, filter.getFullPath(), baseEntityDefinition, parent); + super(context, filter, filter.getFullPath(), null, baseEntityDefinition, parent); } @Override public Condition interpret() throws QueryException { - HqlDataInstance dataInstance = getItemPathResolver().resolveItemPath(filter.getFullPath(), getBaseHqlEntity(), false); + HqlDataInstance dataInstance = getItemPathResolver() + .resolveItemPath(filter.getFullPath(), filter.getDefinition(), getBaseHqlEntity(), false); if (!(dataInstance.getJpaDefinition() instanceof JpaEntityDefinition)) { // should be checked when instantiating this restriction, so now we can throw hard exception throw new IllegalStateException("Internal error - resolutionState for ExistsRestriction points to non-entity node: " + dataInstance.getJpaDefinition()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java index 919547e5815..db657d0c807 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestriction.java @@ -16,11 +16,11 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; +import com.evolveum.midpoint.repo.sql.query2.resolution.HqlDataInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import org.apache.commons.lang.Validate; @@ -33,10 +33,15 @@ public abstract class ItemRestriction extends Restrictio /** * Item path (relative to parent restriction), copied from the appropriate filter. - * Not null, although possibly empty. + * Not null, although possibly empty. (TODO really can be empty?) */ final protected ItemPath itemPath; + /** + * Item definition - necessary only for Any items. + */ + final protected ItemDefinition itemDefinition; + /** * Information about resolved itemPath. Needed when accessing the data. * Contains also information on previous steps, useful to enable looking upwards via ".." operator. @@ -44,13 +49,14 @@ public abstract class ItemRestriction extends Restrictio */ protected HqlDataInstance hqlDataInstance; - public ItemRestriction(InterpretationContext context, T filter, ItemPath itemPath, JpaEntityDefinition baseEntityDefinition, Restriction parent) { + public ItemRestriction(InterpretationContext context, T filter, ItemPath itemPath, ItemDefinition itemDefinition, JpaEntityDefinition baseEntityDefinition, Restriction parent) { super(context, filter, baseEntityDefinition, parent); if (itemPath != null) { this.itemPath = itemPath; } else { this.itemPath = ItemPath.EMPTY_PATH; } + this.itemDefinition = itemDefinition; } public ItemPath getItemPath() { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java index 818a3a18f0a..ccf8c584d1d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemRestrictionOperation.java @@ -21,5 +21,18 @@ */ public enum ItemRestrictionOperation { - EQ, GT, GE, LT, LE, NULL, NOT_NULL, SUBSTRING, STARTS_WITH, ENDS_WITH; + EQ("="), GT(">"), GE(">="), LT("<"), LE("<="), NULL, NOT_NULL, SUBSTRING, STARTS_WITH, ENDS_WITH; + + private String symbol; + + ItemRestrictionOperation() { + } + + ItemRestrictionOperation(String symbol) { + this.symbol = symbol; + } + + public String symbol() { + return symbol; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java index 937eff93007..46162efa05d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/ItemValueRestriction.java @@ -22,10 +22,11 @@ import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.GreaterFilter; import com.evolveum.midpoint.prism.query.LessFilter; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; +import com.evolveum.midpoint.repo.sql.query2.resolution.HqlDataInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; import com.evolveum.midpoint.repo.sql.query2.QueryInterpreter2; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; @@ -38,8 +39,6 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import java.util.List; - /** * Abstract superclass for all value-related filters. There are two major problems solved: * 1) mapping from ItemPath to HQL property paths @@ -56,7 +55,7 @@ public abstract class ItemValueRestriction extends ItemRe private static final Trace LOGGER = TraceManager.getTrace(ItemValueRestriction.class); public ItemValueRestriction(InterpretationContext context, T filter, JpaEntityDefinition baseEntityDefinition, Restriction parent) { - super(context, filter, filter.getFullPath(), baseEntityDefinition, parent); + super(context, filter, filter.getFullPath(), filter.getDefinition(), baseEntityDefinition, parent); } @Override @@ -66,7 +65,7 @@ public Condition interpret() throws QueryException { if (ItemPath.isNullOrEmpty(path)) { throw new QueryException("Null or empty path for ItemValueRestriction in " + filter.debugDump()); } - HqlDataInstance dataInstance = getItemPathResolver().resolveItemPath(path, getBaseHqlEntity(), false); + HqlDataInstance dataInstance = getItemPathResolver().resolveItemPath(path, itemDefinition, getBaseHqlEntity(), false); setHqlDataInstance(dataInstance); Condition condition = interpretInternal(); @@ -75,7 +74,22 @@ public Condition interpret() throws QueryException { public abstract Condition interpretInternal() throws QueryException; - protected Condition createCondition(String hqlPropertyPath, Object value, ValueFilter filter) throws QueryException { + protected Condition createPropertyVsConstantCondition(String hqlPropertyPath, Object value, ValueFilter filter) throws QueryException { + ItemRestrictionOperation operation = findOperationForFilter(filter); + + InterpretationContext context = getContext(); + QueryInterpreter2 interpreter = context.getInterpreter(); + Matcher matcher = interpreter.findMatcher(value); + + String matchingRule = null; + if (filter.getMatchingRule() != null){ + matchingRule = filter.getMatchingRule().getLocalPart(); + } + + return matcher.match(context.getHibernateQuery(), operation, hqlPropertyPath, value, matchingRule); + } + + protected ItemRestrictionOperation findOperationForFilter(ValueFilter filter) throws QueryException { ItemRestrictionOperation operation; if (filter instanceof EqualFilter) { operation = ItemRestrictionOperation.EQ; @@ -97,31 +111,19 @@ protected Condition createCondition(String hqlPropertyPath, Object value, ValueF } else { throw new QueryException("Can't translate filter '" + filter + "' to operation."); } - - InterpretationContext context = getContext(); - QueryInterpreter2 interpreter = context.getInterpreter(); - Matcher matcher = interpreter.findMatcher(value); - - String matchingRule = null; - if (filter.getMatchingRule() != null){ - matchingRule = filter.getMatchingRule().getLocalPart(); - } - - return matcher.match(context.getHibernateQuery(), operation, hqlPropertyPath, value, matchingRule); + return operation; } - protected Object getValue(List values) { - if (values == null || values.isEmpty()) { + protected Object getValue(PropertyValueFilter filter) throws QueryException { + PrismValue val = filter.getSingleValue(); + if (val == null) { return null; - } - - PrismValue val = values.get(0); - if (val instanceof PrismPropertyValue) { + } else if (val instanceof PrismPropertyValue) { PrismPropertyValue propertyValue = (PrismPropertyValue) val; return propertyValue.getValue(); + } else { + throw new QueryException("Non-property value in filter: " + filter + ": " + val.getClass()); } - - return null; } /** diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java index 63d8b395530..fbf7fc5baac 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/PropertyRestriction.java @@ -16,16 +16,15 @@ package com.evolveum.midpoint.repo.sql.query2.restriction; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.ComparativeFilter; import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.PropertyValueFilter; import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.HqlDataInstance; +import com.evolveum.midpoint.repo.sql.query2.resolution.HqlDataInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.ItemPathResolutionState; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaPropertyDefinition; import com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition; @@ -40,10 +39,10 @@ import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; -import java.util.List; /** * @author lazyman + * @author mederly */ public class PropertyRestriction extends ItemValueRestriction { @@ -64,34 +63,47 @@ public Condition interpretInternal() throws QueryException { if (linkDefinition.getTargetDefinition().isLob()) { throw new QueryException("Can't query based on clob property value '" + linkDefinition + "'."); } - List values = filter.getValues(); - if (values != null && values.size() > 1) { - throw new QueryException("Filter '" + filter + "' contain more than one value (which is not supported for now)."); - } - String leftHqlPath = getHqlDataInstance().getHqlPath(); + String propertyValuePath = getHqlDataInstance().getHqlPath(); if (filter.getRightSidePath() != null) { - if (!(filter instanceof EqualFilter)) { - throw new QueryException("Right-side ItemPath is supported currently only for EqualFilter, not for " + filter); - } - HqlDataInstance rightItem = getItemPathResolver().resolveItemPath(filter.getRightSidePath(), - getBaseHqlEntityForChildren(), true); - String rightHqlPath = rightItem.getHqlPath(); - RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + return createPropertyVsPropertyCondition(propertyValuePath); + } else { + Object value = getValueFromFilter(filter); + Condition condition = createPropertyVsConstantCondition(propertyValuePath, value, filter); + return addIsNotNullIfNecessary(condition, propertyValuePath); + } + } + + protected Condition createPropertyVsPropertyCondition(String leftPropertyValuePath) throws QueryException { + HqlDataInstance rightItem = getItemPathResolver().resolveItemPath(filter.getRightSidePath(), + filter.getRightSideDefinition(), getBaseHqlEntityForChildren(), true); + String rightHqlPath = rightItem.getHqlPath(); + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + + // TODO take data types into account, e.g. + // PolyString vs PolyString + // PolyString vs String (and vice versa) + // non-string extension items vs non-string static items + // + // And also take matching rules into account as well. + + if (filter instanceof EqualFilter) { // left = right OR (left IS NULL AND right IS NULL) - Condition condition = hibernateQuery.createEqXY(leftHqlPath, rightHqlPath, "=", false); + Condition condition = hibernateQuery.createCompareXY(leftPropertyValuePath, rightHqlPath, "=", false); OrCondition orCondition = hibernateQuery.createOr( condition, hibernateQuery.createAnd( - hibernateQuery.createIsNull(leftHqlPath), + hibernateQuery.createIsNull(leftPropertyValuePath), hibernateQuery.createIsNull(rightHqlPath) ) ); return orCondition; + } else if (filter instanceof ComparativeFilter) { + ItemRestrictionOperation operation = findOperationForFilter(filter); + Condition condition = hibernateQuery.createCompareXY(leftPropertyValuePath, rightHqlPath, operation.symbol(), false); + return condition; } else { - Object value = getValueFromFilter(filter); - Condition condition = createCondition(leftHqlPath, value, filter); - return addIsNotNullIfNecessary(condition, leftHqlPath); + throw new QueryException("Right-side ItemPath is supported currently only for EqualFilter or ComparativeFilter, not for " + filter); } } @@ -101,7 +113,7 @@ protected Object getValueFromFilter(ValueFilter filter) throws QueryException { Object value; if (filter instanceof PropertyValueFilter) { - value = getValue(((PropertyValueFilter) filter).getValues()); + value = getValue((PropertyValueFilter) filter); } else { throw new QueryException("Unknown filter '" + filter + "', can't get value from it."); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java index 5a5333c1b03..5dae5698dcd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/restriction/Restriction.java @@ -19,9 +19,9 @@ import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query2.HqlEntityInstance; +import com.evolveum.midpoint.repo.sql.query2.resolution.HqlEntityInstance; import com.evolveum.midpoint.repo.sql.query2.InterpretationContext; -import com.evolveum.midpoint.repo.sql.query2.ItemPathResolver; +import com.evolveum.midpoint.repo.sql.query2.resolution.ItemPathResolver; import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition; import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition; import org.apache.commons.lang.Validate; From 01a9dbb0045e9f354518e57e812e04376d5925ff Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 2 Dec 2015 12:20:27 +0100 Subject: [PATCH 055/116] Added page size setup for certification pages and node panel in PageTasks. --- .../web/page/admin/certification/PageCertCampaign.java | 5 ++++- .../web/page/admin/certification/PageCertCampaigns.java | 5 ++++- .../web/page/admin/certification/PageCertDecisions.java | 5 ++++- .../web/page/admin/certification/PageCertDefinitions.java | 5 ++++- .../midpoint/web/page/admin/resources/PageResources.java | 3 ++- .../evolveum/midpoint/web/page/admin/server/PageTasks.java | 4 +++- .../evolveum/midpoint/web/session/UserProfileStorage.java | 7 ++++++- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java index e0ce774ec27..57837b11f1a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java @@ -38,6 +38,7 @@ import com.evolveum.midpoint.web.page.admin.certification.dto.CertCampaignDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertCaseDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertCaseDtoProvider; +import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.web.util.WebModelUtils; @@ -256,7 +257,9 @@ private void initTableLayout(Form mainForm) { provider.setQuery(createCaseQuery()); provider.setCampaignOid(getCampaignOid()); provider.setSort(AccessCertificationCaseType.F_OBJECT_REF.getLocalPart(), SortOrder.ASCENDING); // default sorting - BoxedTablePanel table = new BoxedTablePanel<>(ID_DECISIONS_TABLE, provider, initColumns()); + BoxedTablePanel table = new BoxedTablePanel<>(ID_DECISIONS_TABLE, provider, initColumns(), + UserProfileStorage.TableId.PAGE_CERT_CAMPAIGN_DECISIONS_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_CAMPAIGN_DECISIONS_PANEL)); table.setShowPaging(true); table.setOutputMarkupId(true); mainForm.add(table); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java index 9d4a67c0775..aeec6117089 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java @@ -52,6 +52,7 @@ import com.evolveum.midpoint.web.page.admin.certification.dto.CertCampaignListItemDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertCampaignListItemDtoProvider; import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction; +import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.web.util.WebModelUtils; @@ -262,7 +263,9 @@ public void yesPerformed(AjaxRequestTarget target) { CertCampaignListItemDtoProvider provider = createProvider(); BoxedTablePanel table = new BoxedTablePanel<>( - ID_CAMPAIGNS_TABLE, provider, initColumns()); + ID_CAMPAIGNS_TABLE, provider, initColumns(), + UserProfileStorage.TableId.PAGE_CERT_CAMPAIGNS_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_CAMPAIGNS_PANEL)); table.setShowPaging(true); table.setOutputMarkupId(true); mainForm.add(table); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java index cf5fe435533..c7b0eedc1f9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java @@ -34,6 +34,7 @@ import com.evolveum.midpoint.web.page.admin.certification.dto.CertDecisionDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertDecisionDtoProvider; import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction; +import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.TooltipBehavior; import com.evolveum.midpoint.web.util.WebMiscUtil; @@ -159,7 +160,9 @@ private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); CertDecisionDtoProvider provider = createProvider(); - BoxedTablePanel table = new BoxedTablePanel(ID_DECISIONS_TABLE, provider, initColumns()) { + BoxedTablePanel table = new BoxedTablePanel(ID_DECISIONS_TABLE, provider, initColumns(), + UserProfileStorage.TableId.PAGE_CERT_DECISIONS_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_DECISIONS_PANEL)) { @Override protected WebMarkupContainer createHeader(String headerId) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java index 1318775b6e5..996e8131c2e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java @@ -37,6 +37,7 @@ import com.evolveum.midpoint.web.component.util.SelectableBean; import com.evolveum.midpoint.web.page.admin.configuration.PageDebugView; import com.evolveum.midpoint.web.page.admin.workflow.PageAdminWorkItems; +import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType; @@ -119,7 +120,9 @@ public void yesPerformed(AjaxRequestTarget target) { deleteDefinitionPerformed(target, singleDelete); } }); - BoxedTablePanel table = new BoxedTablePanel<>(ID_DEFINITIONS_TABLE, provider, initColumns()); + BoxedTablePanel table = new BoxedTablePanel<>(ID_DEFINITIONS_TABLE, provider, initColumns(), + UserProfileStorage.TableId.PAGE_CERT_DEFINITIONS_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_DEFINITIONS_PANEL)); table.setShowPaging(false); table.setOutputMarkupId(true); mainForm.add(table); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/PageResources.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/PageResources.java index 537f31ba817..1d97b8f0c5a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/PageResources.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/PageResources.java @@ -173,7 +173,8 @@ private void initLayout() { BoxedTablePanel connectorHosts = new BoxedTablePanel<>(ID_CONNECTOR_TABLE, new ObjectDataProvider(PageResources.this, ConnectorHostType.class), initConnectorHostsColumns(), - UserProfileStorage.TableId.PAGE_RESOURCES_CONNECTOR_HOSTS); + UserProfileStorage.TableId.PAGE_RESOURCES_CONNECTOR_HOSTS, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_RESOURCES_CONNECTOR_HOSTS)); connectorHosts.setOutputMarkupId(true); mainForm.add(connectorHosts); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java index fe11c8a7bff..a5c6dd48ded 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java @@ -202,7 +202,9 @@ protected WebMarkupContainer createHeader(String headerId) { mainForm.add(taskTable); List> nodeColumns = initNodeColumns(); - BoxedTablePanel nodeTable = new BoxedTablePanel(ID_NODE_TABLE, new NodeDtoProvider(PageTasks.this), nodeColumns); + BoxedTablePanel nodeTable = new BoxedTablePanel(ID_NODE_TABLE, new NodeDtoProvider(PageTasks.this), nodeColumns, + UserProfileStorage.TableId.PAGE_TASKS_NODES_PANEL, + (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_TASKS_NODES_PANEL)); nodeTable.setOutputMarkupId(true); nodeTable.setShowPaging(false); mainForm.add(nodeTable); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/session/UserProfileStorage.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/session/UserProfileStorage.java index 24195873dd8..71b1db122b3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/session/UserProfileStorage.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/session/UserProfileStorage.java @@ -46,10 +46,15 @@ public enum TableId { PAGE_RESOURCES_PANEL, PAGE_RESOURCE_ACCOUNTS_PANEL, PAGE_TASKS_PANEL, + PAGE_TASKS_NODES_PANEL, PAGE_USERS_PANEL, PAGE_WORK_ITEMS, PAGE_RESOURCES_CONNECTOR_HOSTS, - PAGE_REPORTS + PAGE_REPORTS, + PAGE_CERT_CAMPAIGN_DECISIONS_PANEL, + PAGE_CERT_CAMPAIGNS_PANEL, + PAGE_CERT_DECISIONS_PANEL, + PAGE_CERT_DEFINITIONS_PANEL } private Map tables = new HashMap(); From 229218952cbd4253e9bd44a4aed37c693bd705ea Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 3 Dec 2015 00:42:07 +0100 Subject: [PATCH 056/116] Preliminary implementation of Fluent Query API. --- .../prism/query/ComparativeFilter.java | 5 + .../midpoint/prism/query/EqualFilter.java | 5 + .../midpoint/prism/query/GreaterFilter.java | 8 + .../midpoint/prism/query/LessFilter.java | 12 +- .../prism/query/NaryLogicalFilter.java | 8 + .../prism/query/PropertyValueFilter.java | 3 +- .../midpoint/prism/query/SubstringFilter.java | 6 +- .../prism/query/builder/FilterBuilder.java | 31 ++ .../prism/query/builder/LogicalSymbol.java | 24 ++ .../prism/query/builder/QueryBuilder.java | 75 ++++ .../prism/query/builder/R_AtomicFilter.java | 242 +++++++++++++ .../prism/query/builder/R_Filter.java | 321 +++++++++++++++++ .../prism/query/builder/R_SimpleFilter.java | 23 ++ .../query/builder/S_AtomicFilterEntry.java | 45 +++ .../query/builder/S_AtomicFilterExit.java | 29 ++ .../query/builder/S_BlockContentEntry.java | 23 ++ .../prism/query/builder/S_ConditionEntry.java | 47 +++ .../prism/query/builder/S_FilterEntry.java | 25 ++ .../query/builder/S_FilterEntryOrEmpty.java | 23 ++ .../prism/query/builder/S_FilterExit.java | 33 ++ .../query/builder/S_MatchingRuleEntry.java | 30 ++ .../prism/query/builder/S_QueryExit.java | 29 ++ .../prism/query/TestQueryBuilder.java | 339 ++++++++++++++++++ infra/prism/testng-unit.xml | 1 + .../repo/sql/QueryInterpreter2Test.java | 178 ++++++--- 25 files changed, 1515 insertions(+), 50 deletions(-) create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/LogicalSymbol.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterExit.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_BlockContentEntry.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntry.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntryOrEmpty.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_MatchingRuleEntry.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java create mode 100644 infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ComparativeFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ComparativeFilter.java index 93ea71b0c1a..e32cde5be8b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ComparativeFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ComparativeFilter.java @@ -46,6 +46,11 @@ public ComparativeFilter() { this.equals = equals; } + public ComparativeFilter(ItemPath path, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + super(path, definition, null, rightSidePath, rightSideDefinition); + this.equals = equals; + } + public boolean isEquals() { return equals; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java index fee95ef50f8..ab428e5ca7c 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java @@ -168,6 +168,11 @@ public static EqualFilter createEqual(ItemPath p return filter; } + public static EqualFilter createEqual(ItemPath propertyPath, PrismPropertyDefinition propertyDefinition, QName matchingRule, ItemPath rightSidePath, ItemDefinition rightSideDefinition) { + EqualFilter filter = new EqualFilter(propertyPath, propertyDefinition, matchingRule, rightSidePath, rightSideDefinition); + return filter; + } + public static EqualFilter createNullEqual(ItemPath itemPath, PrismPropertyDefinition propertyDef, QName matchingRule){ return new EqualFilter(itemPath, propertyDef, matchingRule); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java index 76171b423eb..bb686fc9a1b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java @@ -19,6 +19,7 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -41,6 +42,10 @@ public GreaterFilter() { GreaterFilter(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals) { super(parentPath, definition, value, equals); } + + GreaterFilter(ItemPath parentPath, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + super(parentPath, definition, rightSidePath, rightSideDefinition, equals); + } public static GreaterFilter createGreater(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ return new GreaterFilter(parentPath, definition, value, equals); @@ -131,4 +136,7 @@ public ItemPath getPath() { return getFullPath(); } + public static GreaterFilter createGreaterThanItem(ItemPath itemPath, PrismPropertyDefinition propertyDefinition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + return new GreaterFilter(itemPath, propertyDefinition, rightSidePath, rightSideDefinition, equals); + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java index 67d57e5e228..b56440689d1 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java @@ -19,6 +19,7 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -36,7 +37,12 @@ public class LessFilter extends ComparativeFilter { LessFilter(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals) { super(parentPath, definition, value, equals); } - + + LessFilter(ItemPath parentPath, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + super(parentPath, definition, rightSidePath, rightSideDefinition, equals); + } + + public LessFilter() { } @@ -69,6 +75,10 @@ public static LessFilter createLess(ItemPath parentPath, PrismPropertyDefini return createLess(parentPath, itemDefinition, value, equals); } + public static LessFilter createLessThanItem(ItemPath itemPath, PrismPropertyDefinition propertyDefinition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + return new LessFilter(itemPath, propertyDefinition, rightSidePath, rightSideDefinition, equals); + } + public static LessFilter createLess(ItemPath parentPath, PrismContainerDefinition containerDef, T realValue, boolean equals) throws SchemaException { PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NaryLogicalFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NaryLogicalFilter.java index 44c4d47ae68..35e8dfaf7bb 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NaryLogicalFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NaryLogicalFilter.java @@ -42,4 +42,12 @@ public String debugDump(int indent) { return null; } + public ObjectFilter getLastCondition() { + List conditions = getConditions(); + if (conditions.isEmpty()) { + return null; + } else { + return conditions.get(conditions.size()-1); + } + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java index a0f1b9a5885..75323f4368f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java @@ -371,5 +371,6 @@ public String toString(StringBuilder sb){ } return sb.toString(); } - + + public abstract PropertyValueFilter clone(); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java index fa23a1606c0..b74ce3c4c45 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/SubstringFilter.java @@ -107,8 +107,12 @@ public static SubstringFilter createSubstring(ItemPath path, PrismPropertyDe public static SubstringFilter createSubstring(QName path, PrismPropertyDefinition itemDefinition, QName matchingRule, T realValues) { return createSubstring(new ItemPath(path), itemDefinition, matchingRule, realValues); } - + public static SubstringFilter createSubstring(ItemPath path, PrismPropertyDefinition itemDefinition, QName matchingRule, T realValues) { + return createSubstring(path, itemDefinition, matchingRule, realValues, false, false); + } + + public static SubstringFilter createSubstring(ItemPath path, PrismPropertyDefinition itemDefinition, QName matchingRule, T realValues, boolean anchorStart, boolean anchorEnd) { if (realValues == null){ return createNullSubstring(path, itemDefinition, matchingRule); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java new file mode 100644 index 00000000000..089730da5f7 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.NotFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.OrFilter; + +/** + * @author mederly + */ +public class FilterBuilder { + + + +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/LogicalSymbol.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/LogicalSymbol.java new file mode 100644 index 00000000000..ed8c4d05159 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/LogicalSymbol.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +/** + * @author Pavol + */ +enum LogicalSymbol { + AND, OR +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java new file mode 100644 index 00000000000..d3c12bc9bd8 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.ComplexTypeDefinition; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.AllFilter; +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.NotFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.util.exception.SchemaException; +import org.apache.commons.lang.Validate; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author mederly + */ +public class QueryBuilder { + + final private Class queryClass; + final private ComplexTypeDefinition containerCTD; + final private PrismContext prismContext; + + private QueryBuilder(Class queryClass, PrismContext prismContext) throws SchemaException { + this.queryClass = queryClass; + this.prismContext = prismContext; + containerCTD = prismContext.getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(queryClass); + if (containerCTD == null) { + throw new SchemaException("Couldn't find definition for complex type " + queryClass); + } + } + + public Class getQueryClass() { + return queryClass; + } + + public PrismContext getPrismContext() { + return prismContext; + } + + public static S_FilterEntryOrEmpty queryFor(Class queryClass, PrismContext prismContext) throws SchemaException { + QueryBuilder builder = new QueryBuilder(queryClass, prismContext); + return R_Filter.create(builder); + } + + ItemDefinition findItemDefinition(ItemPath itemPath) throws SchemaException { + ItemDefinition itemDefinition = containerCTD.findItemDefinition(itemPath); + if (itemDefinition == null) { + throw new SchemaException("Couldn't find definition for '" + itemPath + "' in " + containerCTD); + } + return itemDefinition; + } + +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java new file mode 100644 index 00000000000..2f189bc9b68 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismReferenceDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule; +import com.evolveum.midpoint.prism.match.PolyStringOrigMatchingRule; +import com.evolveum.midpoint.prism.match.PolyStringStrictMatchingRule; +import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.EqualFilter; +import com.evolveum.midpoint.prism.query.GreaterFilter; +import com.evolveum.midpoint.prism.query.LessFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.PropertyValueFilter; +import com.evolveum.midpoint.prism.query.SubstringFilter; +import com.evolveum.midpoint.prism.query.ValueFilter; +import com.evolveum.midpoint.util.exception.SchemaException; +import org.apache.commons.lang.Validate; + +import javax.xml.namespace.QName; + +/** + * @author mederly + */ +public class R_AtomicFilter implements S_ConditionEntry, S_MatchingRuleEntry { + + final ItemPath itemPath; + final PrismPropertyDefinition propertyDefinition; + final PrismReferenceDefinition referenceDefinition; + final PropertyValueFilter filter; + final R_Filter owner; + + public R_AtomicFilter(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { + Validate.notNull(itemPath); + Validate.notNull(itemDefinition); + Validate.notNull(owner); + this.itemPath = itemPath; + if (itemDefinition instanceof PrismPropertyDefinition) { + propertyDefinition = (PrismPropertyDefinition) itemDefinition; + referenceDefinition = null; + } else if (itemDefinition instanceof PrismReferenceDefinition) { + propertyDefinition = null; + referenceDefinition = (PrismReferenceDefinition) itemDefinition; + } else { + throw new IllegalStateException("Unsupported item definition: " + itemDefinition); + } + this.filter = null; + this.owner = owner; + } + + public R_AtomicFilter(R_AtomicFilter original, PropertyValueFilter filter) { + Validate.notNull(original); + Validate.notNull(filter); + this.itemPath = original.itemPath; + this.propertyDefinition = original.propertyDefinition; + this.referenceDefinition = original.referenceDefinition; + this.filter = filter; + this.owner = original.owner; + } + + static R_AtomicFilter create(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { + return new R_AtomicFilter(itemPath, itemDefinition, owner); + } + + @Override + public S_MatchingRuleEntry eq(Object value) { + return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, value)); + } + + @Override + public S_MatchingRuleEntry eqPoly(String orig, String norm) { + return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, new PolyString(orig, norm))); + } + + @Override + public S_MatchingRuleEntry eqItem(QName... names) { + ItemPath rightSidePath = new ItemPath(names); + return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, rightSidePath, null)); + } + + @Override + public S_MatchingRuleEntry gt(Object value) throws SchemaException { + return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, value, false)); + } + + @Override + public S_MatchingRuleEntry gtItem(QName... names) throws SchemaException { + ItemPath rightSidePath = new ItemPath(names); + return new R_AtomicFilter(this, GreaterFilter.createGreaterThanItem(itemPath, propertyDefinition, rightSidePath, null, false)); + } + + @Override + public S_MatchingRuleEntry ge(Object value) throws SchemaException { + return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, value, true)); + } + + @Override + public S_MatchingRuleEntry geItem(QName... names) { + ItemPath rightSidePath = new ItemPath(names); + return new R_AtomicFilter(this, GreaterFilter.createGreaterThanItem(itemPath, propertyDefinition, rightSidePath, null, true)); + } + + @Override + public S_MatchingRuleEntry lt(Object value) throws SchemaException { + return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, value, false)); + } + + @Override + public S_MatchingRuleEntry ltItem(QName... names) { + ItemPath rightSidePath = new ItemPath(names); + return new R_AtomicFilter(this, LessFilter.createLessThanItem(itemPath, propertyDefinition, rightSidePath, null, false)); + } + + @Override + public S_MatchingRuleEntry le(Object value) throws SchemaException { + return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, value, true)); + } + + @Override + public S_MatchingRuleEntry leItem(QName... names) { + ItemPath rightSidePath = new ItemPath(names); + return new R_AtomicFilter(this, LessFilter.createLessThanItem(itemPath, propertyDefinition, rightSidePath, null, true)); + } + + @Override + public S_MatchingRuleEntry startsWith(String value) { + return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, null, value, true, false)); + } + + @Override + public S_MatchingRuleEntry endsWith(String value) { + return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, null, value, false, true)); + } + + @Override + public S_MatchingRuleEntry contains(String value) { + return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, null, value, false, false)); + } + + @Override + public S_AtomicFilterExit ref(PrismReferenceValue value) { + throw new UnsupportedOperationException(); + } + + @Override + public S_AtomicFilterExit ref(String oid) { + throw new UnsupportedOperationException(); + } + + @Override + public S_AtomicFilterExit isNull() { + throw new UnsupportedOperationException(); + } + + @Override + public S_AtomicFilterExit matching(QName matchingRuleName) { + PropertyValueFilter clone = filter.clone(); + clone.setMatchingRule(matchingRuleName); + return new R_AtomicFilter(this, clone); + } + + @Override + public S_AtomicFilterExit matchingOrig() { + return matching(PolyStringOrigMatchingRule.NAME); + } + + @Override + public S_AtomicFilterExit matchingNorm() { + return matching(PolyStringNormMatchingRule.NAME); + } + + @Override + public S_AtomicFilterExit matchingStrict() { + return matching(PolyStringStrictMatchingRule.NAME); + } + + @Override + public S_AtomicFilterExit matchingCaseIgnore() { + return matching(StringIgnoreCaseMatchingRule.NAME); + } + + // ============================================================== + // Methods which implement actions common with R_Filter + + @Override + public S_FilterEntry or() throws SchemaException { + return finish().or(); + } + + @Override + public S_FilterEntry and() throws SchemaException { + return finish().and(); + } + + @Override + public ObjectQuery build() throws SchemaException { + return finish().build(); + } + + @Override + public S_QueryExit asc(QName... names) throws SchemaException { + return finish().asc(names); + } + + @Override + public S_QueryExit desc(QName... names) throws SchemaException { + return finish().desc(names); + } + + @Override + public S_AtomicFilterExit endBlock() throws SchemaException { + return finish().endBlock(); + } + + private R_Filter finish() throws SchemaException { + if (filter == null) { + throw new IllegalStateException("Filter is not yet created!"); + } + return owner.addSubfilter(filter); + } + + +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java new file mode 100644 index 00000000000..df29c54bf68 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.ComplexTypeDefinition; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.AllFilter; +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.ExistsFilter; +import com.evolveum.midpoint.prism.query.NoneFilter; +import com.evolveum.midpoint.prism.query.NotFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.query.UndefinedFilter; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; + +/** + * EXPERIMENTAL IMPLEMENTATION. + * + * @author mederly + */ +public class R_Filter implements S_FilterEntryOrEmpty, S_AtomicFilterExit { + + final private QueryBuilder queryBuilder; + final private OrFilter currentFilter; + final private LogicalSymbol lastLogicalSymbol; + final private boolean isNegated; + final private R_Filter parentFilter; + final private QName typeRestriction; + final private ItemPath existsRestriction; + + public R_Filter(QueryBuilder queryBuilder) { + this.queryBuilder = queryBuilder; + this.currentFilter = OrFilter.createOr(); + this.lastLogicalSymbol = null; + this.isNegated = false; + this.parentFilter = null; + this.typeRestriction = null; + this.existsRestriction = null; + } + + private R_Filter(QueryBuilder queryBuilder, OrFilter currentFilter, LogicalSymbol lastLogicalSymbol, + boolean isNegated, R_Filter parentFilter, QName typeRestriction, ItemPath existsRestriction) { + this.queryBuilder = queryBuilder; + this.currentFilter = currentFilter; + this.lastLogicalSymbol = lastLogicalSymbol; + this.isNegated = isNegated; + this.parentFilter = parentFilter; + this.typeRestriction = typeRestriction; + this.existsRestriction = existsRestriction; + } + + public static S_FilterEntryOrEmpty create(QueryBuilder builder) { + return new R_Filter(builder); + } + + // subfilter might be null + R_Filter addSubfilter(ObjectFilter subfilter) throws SchemaException { + if (!currentFilter.isEmpty() && lastLogicalSymbol == null) { + throw new IllegalStateException("lastLogicalSymbol is empty but there is already some filter present: " + currentFilter); + } + if (typeRestriction != null && existsRestriction != null) { + throw new IllegalStateException("Both type and exists restrictions present"); + } + if (typeRestriction != null) { + if (!currentFilter.isEmpty()) { + throw new IllegalStateException("Type restriction with 2 filters?"); + } + if (isNegated) { + subfilter = new NotFilter(subfilter); + } + return parentFilter.addSubfilter(TypeFilter.createType(typeRestriction, subfilter)); + } else if (existsRestriction != null) { + if (!currentFilter.isEmpty()) { + throw new IllegalStateException("Exists restriction with 2 filters?"); + } + if (isNegated) { + subfilter = new NotFilter(subfilter); + } + return parentFilter.addSubfilter( + ExistsFilter.createExists( + existsRestriction, + queryBuilder.getQueryClass(), + queryBuilder.getPrismContext(), + subfilter)); + } else { + OrFilter newFilter = appendAtomicFilter(subfilter, isNegated, lastLogicalSymbol); + return new R_Filter(queryBuilder, newFilter, null, false, parentFilter, typeRestriction, existsRestriction); + } + } + + private OrFilter appendAtomicFilter(ObjectFilter subfilter, boolean negated, LogicalSymbol logicalSymbol) { + if (negated) { + subfilter = new NotFilter(subfilter); + } + OrFilter updatedFilter = currentFilter.clone(); + if (logicalSymbol == null || logicalSymbol == LogicalSymbol.OR) { + updatedFilter.addCondition(AndFilter.createAnd(subfilter)); + } else if (logicalSymbol == LogicalSymbol.AND) { + ((AndFilter) updatedFilter.getLastCondition()).addCondition(subfilter); + } else { + throw new IllegalStateException("Unknown logical symbol: " + logicalSymbol); + } + return updatedFilter; + } + + private R_Filter setLastLogicalSymbol(LogicalSymbol newLogicalSymbol) { + if (this.lastLogicalSymbol != null) { + throw new IllegalStateException("Two logical symbols in a sequence"); + } + return new R_Filter(queryBuilder, currentFilter, newLogicalSymbol, isNegated, parentFilter, typeRestriction, existsRestriction); + } + + private R_Filter setNegated() { + if (isNegated) { + throw new IllegalStateException("Double negation"); + } + return new R_Filter(queryBuilder, currentFilter, lastLogicalSymbol, true, parentFilter, typeRestriction, existsRestriction); + } + + @Override + public S_AtomicFilterExit all() throws SchemaException { + return addSubfilter(AllFilter.createAll()); + } + + @Override + public S_AtomicFilterExit none() throws SchemaException { + return addSubfilter(NoneFilter.createNone()); + } + + @Override + public S_AtomicFilterExit undefined() throws SchemaException { + return addSubfilter(UndefinedFilter.createUndefined()); + } + // TODO ............................................. + + @Override + public S_AtomicFilterExit id(String... identifiers) { + return null; + } + + @Override + public S_AtomicFilterExit id(long... identifiers) { + return null; + } + + @Override + public S_AtomicFilterExit ownerId(String... identifiers) { + return null; + } + + @Override + public S_AtomicFilterExit ownerId(long... identifiers) { + return null; + } + + @Override + public S_AtomicFilterExit isDirectChildOf(PrismReferenceValue value) { + return null; + } + + @Override + public S_AtomicFilterExit isChildOf(PrismReferenceValue value) { + return null; + } + + @Override + public S_AtomicFilterExit isDirectChildOf(String oid) { + return null; + } + + @Override + public S_AtomicFilterExit isChildOf(String oid) { + return null; + } + + @Override + public S_AtomicFilterExit isRoot() { + return null; + } + + @Override + public S_FilterEntryOrEmpty block() { + return new R_Filter(queryBuilder, OrFilter.createOr(), null, false, this, null, null); + } + + @Override + public S_FilterEntry type(Class type) throws SchemaException { + ComplexTypeDefinition ctd = queryBuilder.getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(type); + if (ctd == null) { + throw new SchemaException("Unknown type: " + type); + } + QName typeName = ctd.getTypeName(); + if (typeName == null) { + throw new IllegalStateException("No type name for " + ctd); + } + return new R_Filter(queryBuilder, OrFilter.createOr(), null, false, this, typeName, null); + } + + @Override + public S_FilterEntry exists(QName... names) { + if (existsRestriction != null) { + throw new IllegalStateException("Exists within exists"); + } + ItemPath existsPath = new ItemPath(names); + return new R_Filter(queryBuilder, OrFilter.createOr(), null, false, this, null, existsPath); + } + + // END OF TODO ............................................. + + @Override + public S_FilterEntry and() { + return setLastLogicalSymbol(LogicalSymbol.AND); + } + + @Override + public S_FilterEntry or() { + return setLastLogicalSymbol(LogicalSymbol.OR); + } + + @Override + public S_AtomicFilterEntry not() { + return setNegated(); + } + + @Override + public S_ConditionEntry item(QName... names) throws SchemaException { + ItemPath itemPath = new ItemPath(names); + ItemDefinition itemDefinition = queryBuilder.findItemDefinition(itemPath); + return R_AtomicFilter.create(itemPath, itemDefinition, this); + } + + @Override + public S_AtomicFilterExit endBlock() throws SchemaException { + if (parentFilter == null) { + throw new SchemaException("endBlock() call without preceding block() one"); + } + if (currentFilter != null || parentFilter.hasRestriction()) { + ObjectFilter simplified = simplify(currentFilter); + if (simplified != null || parentFilter.hasRestriction()) { + return parentFilter.addSubfilter(simplified); + } + } + return parentFilter; + } + + private boolean hasRestriction() { + return existsRestriction != null || typeRestriction != null; + } + + @Override + public S_QueryExit asc(QName... names) { + throw new UnsupportedOperationException(); + } + + @Override + public S_QueryExit desc(QName... names) { + throw new UnsupportedOperationException(); + } + + @Override + public ObjectQuery build() throws SchemaException { + if (typeRestriction != null || existsRestriction != null) { + // unfinished empty type restriction or exists restriction + return addSubfilter(null).build(); + } + if (parentFilter != null) { + throw new SchemaException("A block in filter definition was probably not closed."); + } + return ObjectQuery.createObjectQuery(simplify(currentFilter)); + } + + private ObjectFilter simplify(OrFilter filter) { + + if (filter == null) { + return null; + } + + OrFilter simplified = OrFilter.createOr(); + + // step 1 - simplify conjunctions + for (ObjectFilter condition : filter.getConditions()) { + AndFilter conjunction = (AndFilter) condition; + if (conjunction.getConditions().size() == 1) { + simplified.addCondition(conjunction.getLastCondition()); + } else { + simplified.addCondition(conjunction); + } + } + + // step 2 - simplify disjunction + if (simplified.getConditions().size() == 0) { + return null; + } else if (simplified.getConditions().size() == 1) { + return simplified.getLastCondition(); + } else { + return simplified; + } + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java new file mode 100644 index 00000000000..a2e9c5ece7d --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +/** + * @author mederly + */ +public class R_SimpleFilter { +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java new file mode 100644 index 00000000000..9fef393a031 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; + +/** + * @author mederly + */ +public interface S_AtomicFilterEntry { + S_AtomicFilterExit all() throws SchemaException; + S_AtomicFilterExit none() throws SchemaException; + S_AtomicFilterExit undefined() throws SchemaException; + S_ConditionEntry item(QName... names) throws SchemaException; + S_AtomicFilterExit id(String... identifiers); + S_AtomicFilterExit id(long... identifiers); + S_AtomicFilterExit ownerId(String... identifiers); + S_AtomicFilterExit ownerId(long... identifiers); + S_AtomicFilterExit isDirectChildOf(PrismReferenceValue value); + S_AtomicFilterExit isChildOf(PrismReferenceValue value); + S_AtomicFilterExit isDirectChildOf(String oid); + S_AtomicFilterExit isChildOf(String oid); + S_AtomicFilterExit isRoot(); + S_FilterEntryOrEmpty block(); + S_FilterEntry type(Class type) throws SchemaException; + S_FilterEntry exists(QName... names); +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterExit.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterExit.java new file mode 100644 index 00000000000..ec4ec6bfe6d --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterExit.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; + +/** + * @author mederly + */ +public interface S_AtomicFilterExit extends S_FilterExit { + S_FilterEntry or() throws SchemaException; + S_FilterEntry and() throws SchemaException; +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_BlockContentEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_BlockContentEntry.java new file mode 100644 index 00000000000..9fb29e8fa7f --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_BlockContentEntry.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +/** + * @author mederly + */ +public interface S_BlockContentEntry { +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java new file mode 100644 index 00000000000..d6a68c5f616 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; +import java.nio.file.attribute.AclEntry; + +/** + * @author mederly + */ +public interface S_ConditionEntry { + S_MatchingRuleEntry eq(Object value); + S_MatchingRuleEntry eqPoly(String orig, String norm); + S_MatchingRuleEntry eqItem(QName... value); + S_MatchingRuleEntry gt(Object value) throws SchemaException; + S_MatchingRuleEntry gtItem(QName... names) throws SchemaException; + S_MatchingRuleEntry ge(Object value) throws SchemaException; + S_MatchingRuleEntry geItem(QName... names); + S_MatchingRuleEntry lt(Object value) throws SchemaException; + S_MatchingRuleEntry ltItem(QName... names); + S_MatchingRuleEntry le(Object value) throws SchemaException; + S_MatchingRuleEntry leItem(QName... names); + S_AtomicFilterExit startsWith(String value); + S_AtomicFilterExit endsWith(String value); + S_AtomicFilterExit contains(String value); + S_AtomicFilterExit ref(PrismReferenceValue value); + S_AtomicFilterExit ref(String oid); + S_AtomicFilterExit isNull(); +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntry.java new file mode 100644 index 00000000000..495157bd254 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntry.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +/** + * @author mederly + */ +public interface S_FilterEntry extends S_AtomicFilterEntry { + + S_AtomicFilterEntry not(); +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntryOrEmpty.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntryOrEmpty.java new file mode 100644 index 00000000000..ba2d7311a18 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterEntryOrEmpty.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +/** + * @author mederly + */ +public interface S_FilterEntryOrEmpty extends S_FilterEntry, S_FilterExit { +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java new file mode 100644 index 00000000000..57486898910 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; +import java.nio.file.attribute.AclEntry; + +/** + * @author mederly + */ +public interface S_FilterExit extends S_QueryExit { + + S_AtomicFilterExit endBlock() throws SchemaException; + S_QueryExit asc(QName... names) throws SchemaException; + S_QueryExit desc(QName... names) throws SchemaException; +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_MatchingRuleEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_MatchingRuleEntry.java new file mode 100644 index 00000000000..b80f38c0195 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_MatchingRuleEntry.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import javax.xml.namespace.QName; + +/** + * @author mederly + */ +public interface S_MatchingRuleEntry extends S_AtomicFilterExit { + S_AtomicFilterExit matchingOrig(); + S_AtomicFilterExit matchingNorm(); + S_AtomicFilterExit matchingStrict(); + S_AtomicFilterExit matchingCaseIgnore(); + S_AtomicFilterExit matching(QName matchingRuleName); +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java new file mode 100644 index 00000000000..1b90f6be653 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.util.exception.SchemaException; + +/** + * @author mederly + */ +public interface S_QueryExit { + + ObjectQuery build() throws SchemaException; + +} diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java new file mode 100644 index 00000000000..332aa18c891 --- /dev/null +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query; + +import com.evolveum.midpoint.prism.PrismInternalTestUtil; +import com.evolveum.midpoint.prism.foo.AssignmentType; +import com.evolveum.midpoint.prism.foo.UserType; +import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; +import com.evolveum.midpoint.prism.match.MatchingRuleRegistryFactory; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.exception.SchemaException; +import org.testng.AssertJUnit; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +import javax.xml.namespace.QName; +import java.io.IOException; +import java.lang.reflect.Method; + +import static com.evolveum.midpoint.prism.PrismInternalTestUtil.DEFAULT_NAMESPACE_PREFIX; +import static com.evolveum.midpoint.prism.PrismInternalTestUtil.NS_FOO; +import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext; + +/** + * Here are the most simple tests for Query Builder. + * More advanced tests are part of QueryInterpreterTest in repo-sql-impl-test. + */ +public class TestQueryBuilder { + + public static final QName USER_TYPE_QNAME = new QName(NS_FOO, "UserType"); + public static final QName ASSIGNMENT_TYPE_QNAME = new QName(NS_FOO, "AssignmentType"); + private static MatchingRuleRegistry matchingRuleRegistry; + + @BeforeSuite + public void setupDebug() throws SchemaException, SAXException, IOException { + PrettyPrinter.setDefaultNamespacePrefix(DEFAULT_NAMESPACE_PREFIX); + PrismTestUtil.resetPrismContext(new PrismInternalTestUtil()); + + matchingRuleRegistry = MatchingRuleRegistryFactory.createRegistry(); + } + + @BeforeMethod + public void beforeMethod(Method method) throws Exception { + System.out.println(">>>>>>>>>>>>>>>>>>>>>>>> START TEST" + getClass().getName() + "." + method.getName() + "<<<<<<<<<<<<<<<<<<<<<<<<"); + } + + @Test + public void test100EmptyFilter() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).build(); + ObjectQuery expected = ObjectQuery.createObjectQuery((ObjectFilter) null); + compare(actual, expected); + } + + @Test + public void test110EmptyBlock() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).block().endBlock().build(); + ObjectQuery expected = ObjectQuery.createObjectQuery((ObjectFilter) null); + compare(actual, expected); + } + + @Test + public void test112EmptyBlocks() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .block() + .block() + .block() + .endBlock() + .endBlock() + .endBlock() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery((ObjectFilter) null); + compare(actual, expected); + } + + @Test(expectedExceptions = SchemaException.class) + public void test112BlocksLeftOpen() throws Exception{ + QueryBuilder.queryFor(UserType.class, getPrismContext()) + .block() + .block() + .block() + .endBlock() + .endBlock() + .build(); + } + + @Test(expectedExceptions = SchemaException.class) + public void test114NoOpenBlocks() throws Exception{ + QueryBuilder.queryFor(UserType.class, getPrismContext()) + .block() + .block() + .endBlock() + .endBlock() + .endBlock() + .build(); + } + + @Test + public void test120All() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).all().build(); + ObjectQuery expected = ObjectQuery.createObjectQuery(AllFilter.createAll()); + compare(actual, expected); + } + + @Test + public void test122AllInBlock() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).block().all().endBlock().build(); + ObjectQuery expected = ObjectQuery.createObjectQuery(AllFilter.createAll()); + compare(actual, expected); + } + + @Test + public void test130SingleEquals() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()).item(UserType.F_LOCALITY).eq("Caribbean").build(); + ObjectQuery expected = ObjectQuery.createObjectQuery(EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean")); + compare(actual, expected); + } + + @Test + public void test132SingleAnd() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_LOCALITY).eq("Caribbean") + .and().item(UserType.F_DESCRIPTION).eq("desc") + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + AndFilter.createAnd( + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean"), + EqualFilter.createEqual(UserType.F_DESCRIPTION, UserType.class, getPrismContext(), "desc") + ) + ); + compare(actual, expected); + } + + @Test + public void test134SingleOrWithNot() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_LOCALITY).eq("Caribbean") + .or().not().item(UserType.F_DESCRIPTION).eq("desc") + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + OrFilter.createOr( + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean"), + NotFilter.createNot( + EqualFilter.createEqual(UserType.F_DESCRIPTION, UserType.class, getPrismContext(), "desc") + ) + ) + ); + compare(actual, expected); + } + + @Test + public void test136AndOrNotSequence() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_LOCALITY).eq("Caribbean") + .or() + .not().item(UserType.F_DESCRIPTION).eq("desc") + .and().all() + .and().none() + .or() + .undefined() + .and().not().none() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + OrFilter.createOr( + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean"), + AndFilter.createAnd( + NotFilter.createNot( + EqualFilter.createEqual(UserType.F_DESCRIPTION, UserType.class, getPrismContext(), "desc") + ), + AllFilter.createAll(), + NoneFilter.createNone() + ), + AndFilter.createAnd( + UndefinedFilter.createUndefined(), + NotFilter.createNot( + NoneFilter.createNone() + ) + ) + ) + ); + compare(actual, expected); + } + + @Test + public void test140TypeWithEquals() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .item(UserType.F_LOCALITY).eq("Caribbean") + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + TypeFilter.createType( + USER_TYPE_QNAME, + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean") + ) + ); + compare(actual, expected); + } + + @Test + public void test142TypeWithEqualsInBlock() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .block() + .item(UserType.F_LOCALITY).eq("Caribbean") + .endBlock() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + TypeFilter.createType( + USER_TYPE_QNAME, + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean") + ) + ); + compare(actual, expected); + } + + @Test + public void test144TypeWithEqualsAndAllInBlock() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .block() + .item(UserType.F_LOCALITY).eq("Caribbean") + .and().all() + .endBlock() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + TypeFilter.createType( + USER_TYPE_QNAME, + AndFilter.createAnd( + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean"), + AllFilter.createAll() + ) + ) + ); + compare(actual, expected); + } + + @Test + public void test144TypeInTypeInType() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .type(AssignmentType.class) + .type(UserType.class) + .all() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + TypeFilter.createType( + USER_TYPE_QNAME, + TypeFilter.createType( + ASSIGNMENT_TYPE_QNAME, + TypeFilter.createType( + USER_TYPE_QNAME, + AllFilter.createAll() + ) + ) + ) + ); + compare(actual, expected); + } + + @Test + public void test146TypeAndSomething() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .none() + .and().all() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + AndFilter.createAnd( + TypeFilter.createType( + USER_TYPE_QNAME, + NoneFilter.createNone() + ), + AllFilter.createAll() + ) + ); + compare(actual, expected); + } + + @Test + public void test148TypeEmpty() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .block().endBlock() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + TypeFilter.createType( + USER_TYPE_QNAME, + null + ) + ); + compare(actual, expected); + } + + @Test + public void test149TypeEmptyAndAll() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .type(UserType.class) + .block().endBlock() + .and().all() + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + AndFilter.createAnd( + TypeFilter.createType( + USER_TYPE_QNAME, + null + ), + AllFilter.createAll() + ) + ); + compare(actual, expected); + } + + + protected void compare(ObjectQuery actual, ObjectQuery expected) { + String exp = expected.debugDump(); + String act = actual.debugDump(); + System.out.println("Generated query:\n" + act); + AssertJUnit.assertEquals("queries do not match", exp, act); + } + + +} diff --git a/infra/prism/testng-unit.xml b/infra/prism/testng-unit.xml index 4018c54288d..83faa0b7184 100644 --- a/infra/prism/testng-unit.xml +++ b/infra/prism/testng-unit.xml @@ -47,6 +47,7 @@ + diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index e7b29a5c6b3..68902f68442 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -39,6 +39,7 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.prism.query.OrgFilter; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; @@ -151,9 +152,8 @@ public void test001QueryNameNorm() throws Exception { /* * ### user: Equal (name, "asdf", PolyStringNorm) */ - ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, - PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_NAME).eqPoly("asdf", "asdf").matchingNorm().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -179,7 +179,10 @@ public void test002QueryNameOrig() throws Exception { */ ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_NAME).eqPoly("asdf", "asdf").matchingOrig().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -205,7 +208,10 @@ public void test003QueryNameStrict() throws Exception { */ ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, null, new PolyString("asdf", "asdf")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_NAME).eqPoly("asdf", "asdf").build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -231,7 +237,10 @@ public void test010QueryOrganizationNorm() throws Exception { */ ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_ORGANIZATION).eqPoly("asdf", "asdf").matchingNorm().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -257,7 +266,10 @@ public void test011QueryOrganizationOrig() throws Exception { */ ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_ORGANIZATION).eqPoly("asdf", "asdf").matchingOrig().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -284,7 +296,10 @@ public void test012QueryOrganizationStrict() throws Exception { ObjectFilter filter = EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, null, new PolyString("asdf", "asdf")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_ORGANIZATION).eqPoly("asdf", "asdf").matchingStrict().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -313,7 +328,12 @@ public void test020QueryTwoOrganizationsNormAnd() throws Exception { EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringNormMatchingRule.NAME, new PolyString("asdf", "asdf")), EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, PolyStringNormMatchingRule.NAME, new PolyString("ghjk", "ghjk"))); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_ORGANIZATION).eqPoly("asdf", "asdf").matchingNorm() + .and().item(UserType.F_ORGANIZATION).eqPoly("ghjk", "ghjk").matchingNorm() + .build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -343,7 +363,12 @@ public void test021QueryTwoOrganizationsStrictOr() throws Exception { EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, null, new PolyString("asdf", "asdf")), EqualFilter.createEqual(UserType.F_ORGANIZATION, UserType.class, prismContext, null, new PolyString("ghjk", "ghjk"))); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_ORGANIZATION).eqPoly("asdf", "asdf") + .or().item(UserType.F_ORGANIZATION).eqPoly("ghjk", "ghjk") + .build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -423,7 +448,11 @@ public void test040QueryClob() throws Exception { try { ObjectFilter filter = EqualFilter.createEqual(UserType.F_DESCRIPTION, UserType.class, prismContext, null, "aaa"); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(UserType.F_DESCRIPTION).eq("aaa") + .build(); //should throw exception, because description is lob and can't be queried getInterpretedQuery2(session, UserType.class, query); @@ -640,6 +669,13 @@ public void test080QueryExistsAssignment() throws Exception { ObjectQuery query = ObjectQuery.createObjectQuery(filter); query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); +// ObjectQuery query1 = QueryBuilder.queryFor(UserType.class, prismContext) +// .exists(UserType.F_ASSIGNMENT) +// .item(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS) +// .eq(ActivationStatusType.ENABLED) +// .asc(UserType.F_NAME) +// .build(); + String real = getInterpretedQuery2(session, UserType.class, query); String expected = "select\n" + " u.fullObject,\n" + @@ -844,7 +880,13 @@ public void test140QueryUserAccountRef() throws Exception { * l.targetOid = '123' and l.relation = '#' */ RefFilter filter = RefFilter.createReferenceEqual(UserType.F_LINK_REF, UserType.class, prismContext, "123"); - String real = getInterpretedQuery2(session, UserType.class, ObjectQuery.createObjectQuery(filter)); + ObjectQuery query = ObjectQuery.createObjectQuery(filter); + +// ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) +// .item(UserType.F_LINK_REF).ref("123") +// .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); String expected = "select\n" + " u.fullObject,\n" + @@ -1140,32 +1182,6 @@ public void test200QueryTriggerTimestampDoubleWrong() throws Exception { } } - private void addFullObjectProjectionList(String prefix, ProjectionList list, boolean group) { - if (prefix == null) { - prefix = ""; - } else { - prefix = prefix + "."; - } - - if (group) { - list.add(Projections.groupProperty(prefix + "fullObject")); - list.add(Projections.groupProperty(prefix + "stringsCount")); - list.add(Projections.groupProperty(prefix + "longsCount")); - list.add(Projections.groupProperty(prefix + "datesCount")); - list.add(Projections.groupProperty(prefix + "referencesCount")); - list.add(Projections.groupProperty(prefix + "polysCount")); - list.add(Projections.groupProperty(prefix + "booleansCount")); - } else { - list.add(Projections.property(prefix + "fullObject")); - list.add(Projections.property(prefix + "stringsCount")); - list.add(Projections.property(prefix + "longsCount")); - list.add(Projections.property(prefix + "datesCount")); - list.add(Projections.property(prefix + "referencesCount")); - list.add(Projections.property(prefix + "polysCount")); - list.add(Projections.property(prefix + "booleansCount")); - } - } - @Test public void test300CountObjectOrderByName() throws Exception { Session session = open(); @@ -1174,8 +1190,10 @@ public void test300CountObjectOrderByName() throws Exception { EqualFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); - query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + ObjectQuery query = ObjectQuery.createObjectQuery(filter, + ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + +// ObjectQuery query1 = QueryBuilder.queryFor(UserType.class, prismContext).asc(ObjectType.F_NAME).build(); String real = getInterpretedQuery2(session, UserType.class, query, true); String expected = "select\n" + @@ -1247,6 +1265,10 @@ public void test330InOidTest() throws Exception { InOidFilter filter = InOidFilter.createInOid(Arrays.asList("1", "2")); ObjectQuery query = ObjectQuery.createObjectQuery(filter); + +// ObjectQuery query1 = QueryBuilder.queryFor(ObjectType.class, prismContext) +// .id("1", "2").build(); + String real = getInterpretedQuery2(session, ObjectType.class, query, false); String expected = "select\n" + " o.fullObject,\n" + @@ -1277,6 +1299,11 @@ public void test340QueryOrgTreeFindOrgs() throws Exception { objectQuery.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); objectQuery.setUseNewQueryInterpreter(true); +// ObjectQuery query1 = QueryBuilder.queryFor(OrgType.class, prismContext) +// .isDirectChildOf("some oid") +// .asc(ObjectType.F_NAME) +// .build(); + String real = getInterpretedQuery2(session, OrgType.class, objectQuery); OperationResult result = new OperationResult("query org structure"); @@ -1345,15 +1372,22 @@ public void test400ActivationQueryWrong() throws Exception { thisScanTimestamp, true), LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true) ); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext) + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .or().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .or().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .or().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .build(); Session session = open(); try { - ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + @@ -1405,10 +1439,20 @@ public void test405ActivationQueryCorrect() throws Exception { assignmentDef, thisScanTimestamp, true), LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), assignmentDef, thisScanTimestamp, true)))); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext) + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .or().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .or().exists(FocusType.F_ASSIGNMENT) + .block() + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .or().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .build(); Session session = open(); try { - ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + @@ -1472,10 +1516,31 @@ public void test410ActivationQueryWrong() throws Exception { focusObjectDef, thisScanTimestamp, true) ) ); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext) + .block() + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) + .and().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .endBlock() + .or().block() + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).gt(lastScanTimestamp) + .and().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .or().block() + .item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) + .and().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .endBlock() + .or().block() + .item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).gt(lastScanTimestamp) + .and().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .build(); + + //QueryBuilder.queryFor(UserType.class, prismContext); Session session = open(); try { - ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + @@ -1512,7 +1577,6 @@ public void test410ActivationQueryWrong() throws Exception { " )\n" + " )\n"; - // TODO rewrite with ForValue assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -1559,10 +1623,30 @@ public void test415ActivationQueryCorrect() throws Exception { assignmentDef, thisScanTimestamp, true)))) ) ); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + + ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext) + .block() + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) + .and().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .endBlock() + .or().block() + .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).gt(lastScanTimestamp) + .and().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .or() + .exists(FocusType.F_ASSIGNMENT) + .block() + .item(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) + .and().item(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .or() + .item(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).gt(lastScanTimestamp) + .and().item(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .build(); Session session = open(); try { - ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, UserType.class, query, false); String expected = "select\n" + From 8c6057ecdb3e12084e4749eb0e32fbb145d38159 Mon Sep 17 00:00:00 2001 From: honchar Date: Thu, 3 Dec 2015 16:04:06 +0100 Subject: [PATCH 057/116] Associations editable panel. not finished yet --- .../web/component/prism/ContainerWrapper.java | 2 +- .../web/component/prism/PrismValuePanel.java | 111 ++++++++++++++---- 2 files changed, 86 insertions(+), 27 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java index 9d491ffd02c..175e08a8c13 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java @@ -278,7 +278,7 @@ private List createProperties(PageBase pageBase) { if (object.getAssociations() != null) { for (PrismProperty property : object.getAssociations()) { // TODO: fix this -> for now, read only is supported.. - PropertyWrapper propertyWrapper = new PropertyWrapper(this, property, true, + PropertyWrapper propertyWrapper = new PropertyWrapper(this, property, false, ValueStatus.NOT_CHANGED); properties.add(propertyWrapper); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index b07de6afd5f..624b07b0177 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -26,10 +26,24 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.parser.QueryConvertor; +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.EqualFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.page.admin.PageAdminFocus; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.Validate; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; +import org.apache.wicket.MarkupContainer; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; @@ -38,6 +52,7 @@ import org.apache.wicket.extensions.yui.calendar.DateTimeField; import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.TextField; @@ -48,16 +63,6 @@ import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; -import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.prism.PrismReferenceDefinition; -import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.xml.XsdTypeMapper; @@ -89,15 +94,6 @@ import com.evolveum.midpoint.web.util.DateValidator; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.web.util.WebModelUtils; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LockoutStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AssignmentCreationApprovalFormType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; @@ -110,6 +106,9 @@ public class PrismValuePanel extends Panel { private static final String ID_FEEDBACK = "feedback"; private static final String ID_INPUT = "input"; private static final String ID_VALUE_CONTAINER = "valueContainer"; + private static final String DOT_CLASS = PrismValuePanel.class.getName() + "."; + private static final String OPERATION_LOAD_ASSOC_SHADOWS = DOT_CLASS + "loadAssociationShadows"; + private static final Trace LOGGER = TraceManager.getTrace(PrismValuePanel.class); private IModel model; private PageBase pageBase; @@ -411,16 +410,49 @@ private Panel createTypedInputComponent(String id) { final String baseExpression = "value.value"; //pointing to prism property real value - ContainerWrapper containerWrapper = model.getObject().getItem().getContainer(); + ItemWrapper itemWrapper = model.getObject().getItem(); + ContainerWrapper containerWrapper = itemWrapper.getContainer(); if(containerWrapper != null && containerWrapper.getPath() != null){ if(ShadowType.F_ASSOCIATION.getLocalPart().equals(containerWrapper.getPath().toString())){ - return new TextDetailsPanel(id, new PropertyModel(model, baseExpression)){ + Class typeFromName = null; + PrismContext prismContext = item.getPrismContext(); + if (prismContext == null) { + prismContext = pageBase.getPrismContext(); + } - @Override - public String createAssociationTooltip(){ - return createAssociationTooltipText(property); - } - }; + PrismContainerValue assocContainer = (PrismContainerValue)item.getParent(); + PrismProperty assocObjectClassItem = (PrismProperty)assocContainer.findItem(ShadowType.F_OBJECT_CLASS); + QName objectClassName = null; + if (assocObjectClassItem != null && assocObjectClassItem.getValues() != null + && assocObjectClassItem.getValues().size() > 0) { + objectClassName = (QName)((PrismPropertyValue)assocObjectClassItem.getValues().get(0)).getValue(); + } + + PrismProperty kindItem = (PrismProperty)assocContainer.findItem(ShadowType.F_KIND); + ShadowKindType shadowKindType = null; + if (kindItem != null){ + shadowKindType = kindItem.getValues() != null && kindItem.getValues().size() > 0 ? + (ShadowKindType)((PrismPropertyValue)kindItem.getValues().get(0)).getValue() : null; + } + + PrismProperty intentItem = (PrismProperty)assocContainer.findItem(ShadowType.F_INTENT); + String intentValue = ""; + if (intentItem != null){ + intentValue = intentItem.getValues() != null && intentItem.getValues().size() > 0 ? + (String)((PrismPropertyValue)intentItem.getValues().get(0)).getValue() : ""; + } + + List> values = loadAssociationShadows(assocObjectClassItem, kindItem, intentItem); + + return new ValueChoosePanel(id, + new PropertyModel<>(model, "value"), values, false, ShadowType.class); +// return new TextDetailsPanel(id, new PropertyModel(model, baseExpression)){ +// +// @Override +// public String createAssociationTooltip(){ +// return createAssociationTooltipText(property); +// } +// }; } } @@ -765,4 +797,31 @@ private void removeValue(AjaxRequestTarget target) { ListView parent = findParent(ListView.class); target.add(parent.getParent()); } + + private List> loadAssociationShadows(PrismProperty objectClass, PrismProperty kind, + PrismProperty intent) { + Task task = pageBase.createSimpleTask(OPERATION_LOAD_ASSOC_SHADOWS); + OperationResult result = new OperationResult(OPERATION_LOAD_ASSOC_SHADOWS); + + List> assocShadows = null; + try { + ObjectFilter andFilter = AndFilter.createAnd(EqualFilter.createEqual(new ItemPath(ShadowType.F_OBJECT_CLASS), objectClass), + EqualFilter.createEqual(new ItemPath(ShadowType.F_KIND), kind), + EqualFilter.createEqual(new ItemPath(ShadowType.F_INTENT), intent)); + ObjectQuery objectQuery = ObjectQuery.createObjectQuery(andFilter); + + objectQuery.setFilter(andFilter); + Collection> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch()); + + assocShadows = pageBase.getModelService().searchObjects(ShadowType.class, new ObjectQuery(), null, task, result); + } catch (Exception ex) { + LoggingUtils.logException(LOGGER, "Unable to load association shadow", ex); + result.recordFatalError("Unable to load association shadow", ex); + } finally { + result.computeStatus(); + } + + return assocShadows; + } + } From 0b5a147c5c844f9b31212f0b89bc040641081b03 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 3 Dec 2015 19:27:44 +0100 Subject: [PATCH 058/116] Fixed various access certification problems. Enhancements in Query API. "My cases to decide" shows only really relevant cases. "Show 'no response' cases only" now works. Fixed random reorderings of cases that have the same value of sorting criterion. Major cert campaign properties are now searchable. Pre-creation of empty cert decisions on stage opening. BEWARE: repository schema change for cert cases! Allowing multiple sorting criteria in ObjectPaging. Added OID ("#") as a possible sorting criterion. Fluent Query API improvements. Not complete yet, though. --- .../certification/PageCertCampaigns.java | 6 +- .../certification/dto/CertCampaignDto.java | 4 +- .../dto/CertCampaignListItemDto.java | 4 +- .../admin/certification/dto/CertCaseDto.java | 2 +- .../dto/CertCaseOrDecisionDto.java | 4 +- .../midpoint/prism/PrismConstants.java | 1 + .../prism/path/IdentifierPathSegment.java | 41 ++++ .../midpoint/prism/path/ItemPath.java | 14 +- .../prism/path/ReferencePathSegment.java | 2 +- .../midpoint/prism/query/EqualFilter.java | 3 +- .../midpoint/prism/query/GreaterFilter.java | 5 +- .../midpoint/prism/query/LessFilter.java | 4 +- .../midpoint/prism/query/ObjectOrdering.java | 53 ++++ .../midpoint/prism/query/ObjectPaging.java | 115 +++++---- .../midpoint/prism/query/ObjectQuery.java | 8 +- .../prism/query/PropertyValueFilter.java | 46 +++- .../midpoint/prism/query/RefFilter.java | 4 +- .../prism/query/builder/QueryBuilder.java | 14 +- .../prism/query/builder/R_AtomicFilter.java | 90 +++++-- .../prism/query/builder/R_Filter.java | 100 ++++++-- .../query/builder/S_AtomicFilterEntry.java | 5 +- .../prism/query/builder/S_ConditionEntry.java | 13 +- .../prism/query/builder/S_FilterExit.java | 4 +- .../prism/query/builder/S_QueryExit.java | 2 + .../query/builder/S_RightHandItemEntry.java | 32 +++ .../src/main/resources/xml/ns/test/foo-1.xsd | 1 + .../midpoint/prism/TestPrismContext.java | 2 +- .../midpoint/prism/foo/AssignmentType.java | 11 + .../midpoint/prism/foo/ObjectFactory.java | 1 + .../prism/query/TestQueryBuilder.java | 211 +++++++++++++++- .../schema/util/CertCampaignTypeUtil.java | 6 +- .../xml/ns/public/common/common-3.xsd | 30 ++- .../impl/AccCertEventHelper.java | 4 +- .../impl/AccCertGeneralHelper.java | 2 +- .../impl/AccCertQueryHelper.java | 130 +++++++--- .../AccCertResponseComputationHelper.java | 10 +- .../impl/AccCertUpdateHelper.java | 76 ++++-- ...onCloseStageApproachingTriggerHandler.java | 4 +- ...CertificationCloseStageTriggerHandler.java | 2 +- .../impl/CertificationManagerImpl.java | 10 +- .../test/AbstractCertificationTest.java | 16 +- .../test/BasicCertificationTest.java | 11 +- .../test/CriticalRolesCertificationTest.java | 2 +- .../test/RoleInducementCertificationTest.java | 4 +- .../src/test/resources/logback-test.xml | 1 + .../api/events/AccessCertificationEvent.java | 2 +- .../api/events/CertReviewEvent.java | 2 +- .../impl/helpers/CertHelper.java | 4 +- .../midpoint/repo/sql/OrgStructTest.java | 3 +- .../repo/sql/QueryInterpreter2Test.java | 232 +++++++++++------- .../common/RAccessCertificationCampaign.java | 109 ++++++-- .../repo/sql/data/common/RObject.java | 3 +- .../container/RAccessCertificationCase.java | 39 ++- .../RAccessCertificationDecision.java | 6 +- .../data/common/container/RAssignment.java | 3 +- .../sql/data/common/container/RExclusion.java | 2 + .../sql/data/common/container/RTrigger.java | 3 +- .../RAccessCertificationCampaignState.java | 45 ++++ .../data/common/other/RLookupTableRow.java | 2 + .../sql/helpers/CertificationCaseHelper.java | 6 +- .../repo/sql/query2/QueryInterpreter2.java | 46 ++-- .../definition/ClassDefinitionParser.java | 16 +- .../query2/definition/IdQueryProperty.java | 33 +++ .../repo/sql/query2/hqm/HibernateQuery.java | 41 +++- 64 files changed, 1289 insertions(+), 418 deletions(-) create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/path/IdentifierPathSegment.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_RightHandItemEntry.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationCampaignState.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java index aeec6117089..bef3efea613 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java @@ -627,7 +627,7 @@ private void startSelectedCampaignsPerformed(AjaxRequestTarget target) { } protected String determineAction(AccessCertificationCampaignType campaign) { - int currentStage = campaign.getCurrentStageNumber(); + int currentStage = campaign.getStageNumber(); int numOfStages = CertCampaignTypeUtil.getNumberOfStages(campaign); AccessCertificationCampaignStateType state = campaign.getState(); String button; @@ -674,7 +674,7 @@ private void openNextStagePerformed(AjaxRequestTarget target, AccessCertificatio CertificationManager cm = getCertificationManager(); try { Task task = createSimpleTask(OPERATION_OPEN_NEXT_STAGE); - int currentStage = campaign.getCurrentStageNumber(); + int currentStage = campaign.getStageNumber(); cm.openNextStage(campaign.getOid(), currentStage + 1, task, result); } catch (Exception ex) { result.recordFatalError(ex); @@ -714,7 +714,7 @@ private void closeStageConfirmedPerformed(AjaxRequestTarget target, CertCampaign try { CertificationManager cm = getCertificationManager(); Task task = createSimpleTask(OPERATION_CLOSE_STAGE); - cm.closeCurrentStage(campaign.getOid(), campaign.getCurrentStageNumber(), task, result); + cm.closeCurrentStage(campaign.getOid(), campaign.getStageNumber(), task, result); }catch (Exception ex) { result.recordFatalError(ex); } finally { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignDto.java index 888eae15afc..ea8e2385804 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignDto.java @@ -102,7 +102,7 @@ public int getNumberOfStages() { } private String resolveCurrentStateName(PageBase page) { - int stageNumber = campaign.getCurrentStageNumber(); + int stageNumber = campaign.getStageNumber(); AccessCertificationCampaignStateType state = campaign.getState(); switch (state) { case CREATED: @@ -143,7 +143,7 @@ public AccessCertificationCampaignStateType getState() { } public int getCurrentStageNumber() { - return campaign.getCurrentStageNumber(); + return campaign.getStageNumber(); } public String getHandlerUri() { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignListItemDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignListItemDto.java index a905e993cf2..58c70f3e814 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignListItemDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCampaignListItemDto.java @@ -83,7 +83,7 @@ public String getDescription() { } public Integer getCurrentStageNumber() { - int currentStage = campaign.getCurrentStageNumber(); + int currentStage = campaign.getStageNumber(); if (AccessCertificationCampaignStateType.IN_REVIEW_STAGE.equals(campaign.getState()) || AccessCertificationCampaignStateType.REVIEW_STAGE_DONE.equals(campaign.getState())) { return currentStage; @@ -100,7 +100,7 @@ private String computeDeadlineAsString(PageBase page) { AccessCertificationStageType currentStage = CertCampaignTypeUtil.getCurrentStage(campaign); XMLGregorianCalendar end; Boolean stageLevelInfo; - if (campaign.getCurrentStageNumber() == 0) { + if (campaign.getStageNumber() == 0) { end = campaign.getEnd(); stageLevelInfo = false; } else if (currentStage != null) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseDto.java index ba6c3a5e418..1403b1a43a7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseDto.java @@ -98,7 +98,7 @@ public AccessCertificationResponseType getCurrentResponse() { } public Integer getCurrentResponseStageNumber() { - return getCertCase().getCurrentResponseStage(); + return getCertCase().getCurrentStageNumber(); } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrDecisionDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrDecisionDto.java index c234415060c..56d207b82dd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrDecisionDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/CertCaseOrDecisionDto.java @@ -115,7 +115,7 @@ public String getCampaignName() { public Integer getCampaignStageNumber() { AccessCertificationCampaignType campaign = getCampaign(); - return campaign != null ? campaign.getCurrentStageNumber() : null; // numbers after # of stages should not occur, as there are no cases in these stages + return campaign != null ? campaign.getStageNumber() : null; // numbers after # of stages should not occur, as there are no cases in these stages } public Integer getCampaignStageCount() { @@ -133,7 +133,7 @@ public Date getStageStarted() { if (campaign == null) { return null; } - int stageNumber = campaign.getCurrentStageNumber(); + int stageNumber = campaign.getStageNumber(); if (stageNumber <= 0 || stageNumber > CertCampaignTypeUtil.getNumberOfStages(campaign)) { return null; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java index 69008729574..82b27ad3f3b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java @@ -95,6 +95,7 @@ public class PrismConstants { // Path constants public static final QName T_PARENT = new QName(NS_TYPES, "parent"); public static final QName T_OBJECT_REFERENCE = new QName(NS_TYPES, "objectReference"); + public static final QName T_ID = new QName(NS_TYPES, "id"); // Misc diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/IdentifierPathSegment.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/IdentifierPathSegment.java new file mode 100644 index 00000000000..46809c17912 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/IdentifierPathSegment.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.path; + +/** + * Denotes identifier of the object or container (i.e. OID or container ID). + * Currently supported only for sorting (not even for filtering!). + * + * @author mederly + */ +public class IdentifierPathSegment extends ItemPathSegment { + + @Override + public boolean equivalent(Object obj) { + return equals(obj); + } + + @Override + public ItemPathSegment clone() { + return new IdentifierPathSegment(); + } + + @Override + public String toString() { + return "#"; + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index 7f264f6e3e1..0d58f6edcbf 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -73,6 +73,8 @@ private QName stringToQName(String name) { return PrismConstants.T_PARENT; } else if ("@".equals(name)) { return PrismConstants.T_OBJECT_REFERENCE; + } else if ("#".equals(name)) { + return PrismConstants.T_ID; } else { return new QName(name); } @@ -151,6 +153,8 @@ private void add(QName qname) { this.segments.add(new ParentPathSegment()); } else if (PrismConstants.T_OBJECT_REFERENCE.equals(qname)) { this.segments.add(new ObjectReferencePathSegment()); + } else if (PrismConstants.T_ID.equals(qname)) { + this.segments.add(new IdentifierPathSegment()); } else { this.segments.add(new NameItemPathSegment(qname)); } @@ -573,13 +577,13 @@ public ItemPath clone() { return clone; } - public static boolean containsReferences(ItemPath path) { - return path != null && path.containsReferences(); + public static boolean containsSpecialSymbols(ItemPath path) { + return path != null && path.containsSpecialSymbols(); } - public boolean containsReferences() { + public boolean containsSpecialSymbols() { for (ItemPathSegment segment : segments) { - if (segment instanceof ReferencePathSegment) { + if (segment instanceof ReferencePathSegment || segment instanceof IdentifierPathSegment) { return true; } } @@ -587,7 +591,7 @@ public boolean containsReferences() { } public static void checkNoReferences(ItemPath path) { - if (containsReferences(path)) { + if (containsSpecialSymbols(path)) { throw new IllegalStateException("Item path shouldn't contain references but it does: " + path); } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java index c3049e865a9..6f5f8b82edc 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ReferencePathSegment.java @@ -18,7 +18,7 @@ /** * Denotes reference path segment: either ".." meaning owner, or "@" meaning referenced object. - * (Note that these are to be used only in filters, for now.) + * (Note that these are to be used only in filters and order instructions, for now.) * * @author mederly */ diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java index ab428e5ca7c..d32767f0d34 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/EqualFilter.java @@ -183,6 +183,7 @@ public EqualFilter clone() { EqualFilter clone = new EqualFilter(getFullPath(), getDefinition(), getMatchingRule(), (List>) getValues()); clone.setExpression(getExpression()); cloneValues(clone); + clone.copyRightSideThingsFrom(this); return clone; } @@ -202,7 +203,7 @@ public String debugDump(int indent) { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("EQUAL("); + sb.append("EQUAL: "); return toString(sb); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java index bb686fc9a1b..d0e64885063 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java @@ -25,7 +25,6 @@ import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; @@ -88,7 +87,9 @@ public static GreaterFilter createGreater(ItemPath pat @Override public GreaterFilter clone() { - return new GreaterFilter(getFullPath(), getDefinition(), (PrismPropertyValue) getValues().get(0), isEquals()); + GreaterFilter clone = new GreaterFilter(getFullPath(), getDefinition(), getSingleValue(), isEquals()); + clone.copyRightSideThingsFrom(this); + return clone; } @Override diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java index b56440689d1..6e6ae02cde2 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java @@ -99,7 +99,9 @@ public static LessFilter createLess(ItemPath path, Cla } @Override public LessFilter clone() { - return new LessFilter(getFullPath(), getDefinition(), (PrismPropertyValue) getValues().get(0), isEquals()); + LessFilter clone = new LessFilter(getFullPath(), getDefinition(), getSingleValue(), isEquals()); + clone.copyRightSideThingsFrom(this); + return clone; } @Override diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java new file mode 100644 index 00000000000..169c5e4af00 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query; + +import com.evolveum.midpoint.prism.path.ItemPath; + +/** + * @author mederly + */ +public class ObjectOrdering { + + final private ItemPath orderBy; + final private OrderDirection direction; + + ObjectOrdering(ItemPath orderBy, OrderDirection direction) { + if (ItemPath.isNullOrEmpty(orderBy)) { + throw new IllegalArgumentException("Null or empty ordering path is not supported."); + } + this.orderBy = orderBy; + this.direction = direction; + } + + public static ObjectOrdering createOrdering(ItemPath orderBy, OrderDirection direction) { + return new ObjectOrdering(orderBy, direction); + } + + public ItemPath getOrderBy() { + return orderBy; + } + + public OrderDirection getDirection() { + return direction; + } + + @Override + public String toString() { + return orderBy.toString() + " " + direction; + } +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java index 14f08d24bc5..4708c9dc1c2 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectPaging.java @@ -17,6 +17,10 @@ package com.evolveum.midpoint.prism.query; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import javax.xml.namespace.QName; @@ -28,12 +32,10 @@ public class ObjectPaging implements DebugDumpable, Serializable { private Integer offset; private Integer maxSize; - private ItemPath orderBy; - private OrderDirection direction; + private List ordering = new ArrayList<>(); private String cookie; protected ObjectPaging() { - // TODO Auto-generated constructor stub } ObjectPaging(Integer offset, Integer maxSize) { @@ -41,16 +43,14 @@ protected ObjectPaging() { this.maxSize = maxSize; } - public ObjectPaging(ItemPath orderBy, OrderDirection direction) { - this.orderBy = orderBy; - this.direction = direction; + ObjectPaging(ItemPath orderBy, OrderDirection direction) { + setOrdering(orderBy, direction); } ObjectPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction) { this.offset = offset; this.maxSize = maxSize; - this.orderBy = orderBy; - this.direction = direction; + setOrdering(orderBy, direction); } public static ObjectPaging createPaging(Integer offset, Integer maxSize){ @@ -72,18 +72,65 @@ public static ObjectPaging createPaging(Integer offset, Integer maxSize, String public static ObjectPaging createPaging(ItemPath orderBy, OrderDirection direction) { return new ObjectPaging(orderBy, direction); } + + public static ObjectPaging createPaging(QName orderBy, OrderDirection direction) { + return new ObjectPaging(new ItemPath(orderBy), direction); + } public static ObjectPaging createEmptyPaging(){ return new ObjectPaging(); } - + + // TODO rename to getPrimaryOrderingDirection public OrderDirection getDirection() { - return direction; + ObjectOrdering primary = getPrimaryOrdering(); + return primary != null ? primary.getDirection() : null; + } + + // TODO rename to getPrimaryOrderingPath + public ItemPath getOrderBy() { + ObjectOrdering primary = getPrimaryOrdering(); + return primary != null ? primary.getOrderBy() : null; } - public void setDirection(OrderDirection direction) { - this.direction = direction; + + public ObjectOrdering getPrimaryOrdering() { + if (hasOrdering()) { + return ordering.get(0); + } else { + return null; + } } - + + // TODO name? + public List getOrderingInstructions() { + return ordering; + } + + public boolean hasOrdering() { + return ordering != null && !ordering.isEmpty(); // first is just for sure + } + + public void setOrdering(ItemPath orderBy, OrderDirection direction) { + this.ordering = new ArrayList<>(); + addOrderingInstruction(orderBy, direction); + } + + public void addOrderingInstruction(ItemPath orderBy, OrderDirection direction) { + this.ordering.add(new ObjectOrdering(orderBy, direction)); + } + + public void addOrderingInstruction(QName orderBy, OrderDirection direction) { + addOrderingInstruction(new ItemPath(orderBy), direction); + } + + public void setOrdering(ObjectOrdering... orderings) { + this.ordering = new ArrayList<>(Arrays.asList(orderings)); + } + + public void setOrdering(Collection orderings) { + this.ordering = new ArrayList<>(orderings); + } + public Integer getOffset() { return offset; } @@ -91,19 +138,7 @@ public Integer getOffset() { public void setOffset(Integer offset) { this.offset = offset; } - - public ItemPath getOrderBy() { - return orderBy; - } - - public void setOrderBy(QName orderBy) { - this.orderBy = new ItemPath(orderBy); - } - public void setOrderBy(ItemPath orderBy) { - this.orderBy = orderBy; - } - public Integer getMaxSize() { return maxSize; } @@ -151,8 +186,11 @@ public ObjectPaging clone() { protected void copyTo(ObjectPaging clone) { clone.offset = this.offset; clone.maxSize = this.maxSize; - clone.orderBy = this.orderBy; - clone.direction = this.direction; + if (this.ordering != null) { + clone.ordering = new ArrayList<>(this.ordering); + } else { + clone.ordering = null; + } clone.cookie = this.cookie; } @@ -164,7 +202,7 @@ public String debugDump() { @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); - sb.append("PAGING:"); + sb.append("Paging:"); if (getOffset() != null) { sb.append("\n"); DebugUtil.indentDebugDump(sb, indent + 1); @@ -175,15 +213,10 @@ public String debugDump(int indent) { DebugUtil.indentDebugDump(sb, indent + 1); sb.append("Max size: " + getMaxSize()); } - if (getOrderBy() != null) { + if (hasOrdering()) { sb.append("\n"); DebugUtil.indentDebugDump(sb, indent + 1); - sb.append("Order by: " + getOrderBy().toString()); - } - if (getDirection() != null) { - sb.append("\n"); - DebugUtil.indentDebugDump(sb, indent + 1); - sb.append("Order direction: " + getDirection()); + sb.append("Ordering: ").append(ordering); } if (getCookie() != null) { sb.append("\n"); @@ -211,14 +244,9 @@ public String toString() { sb.append(getMaxSize()); sb.append(","); } - if (getOrderBy() != null){ - sb.append("BY: "); - sb.append(getOrderBy()); - sb.append(", "); - } - if (getDirection() != null){ - sb.append("D:"); - sb.append(getDirection()); + if (hasOrdering()) { + sb.append("ORD: "); + sb.append(ordering); sb.append(", "); } if (getCookie() != null) { @@ -228,5 +256,4 @@ public String toString() { return sb.toString(); } - } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java index b7202f569eb..ffd63391783 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectQuery.java @@ -131,9 +131,9 @@ public String debugDump(int indent) { DebugUtil.indentDebugDump(sb, indent); if (filter == null) { - sb.append("filter: null"); + sb.append("Filter: null"); } else { - sb.append("filter:"); + sb.append("Filter:"); sb.append("\n"); sb.append(filter.debugDump(indent + 1)); } @@ -141,9 +141,9 @@ public String debugDump(int indent) { sb.append("\n"); DebugUtil.indentDebugDump(sb, indent); if (paging == null) { - sb.append("paging: null"); + sb.append("Paging: null"); } else { - sb.append("paging: ").append(paging.debugDump(0)); + sb.append(paging.debugDump(0)); } if (allowPartialResults) { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java index 75323f4368f..7c4f99b05b7 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/PropertyValueFilter.java @@ -60,6 +60,10 @@ public abstract class PropertyValueFilter extends ValueFil private ItemPath rightSidePath; // alternative to "values" private ItemDefinition rightSideDefinition; // optional (needed only if path points to extension item) + /* + * TODO clean up the right side path/definition mess + */ + PropertyValueFilter() { super(); } @@ -150,7 +154,7 @@ public List getValues() { } public T getSingleValue() { - if (values == null) { + if (values == null || values.isEmpty()) { return null; } if (values.size() > 1) { @@ -218,6 +222,17 @@ public ItemDefinition getRightSideDefinition() { return rightSideDefinition; } + public void setRightSidePath(ItemPath rightSidePath) { + this.rightSidePath = rightSidePath; + if (rightSidePath != null) { + values = null; + } + } + + public void setRightSideDefinition(ItemDefinition rightSideDefinition) { + this.rightSideDefinition = rightSideDefinition; + } + public ExpressionWrapper getExpression() { return expression; } @@ -340,6 +355,21 @@ public String debugDump(int indent, StringBuilder sb){ sb.append(DebugUtil.debugDump(expression.getExpression(), indent + 2)); } + if (getRightSidePath() != null) { + sb.append("\n"); + DebugUtil.indentDebugDump(sb, indent+1); + sb.append("RIGHT SIDE PATH: "); + sb.append(getFullPath().toString()); + sb.append("\n"); + DebugUtil.indentDebugDump(sb, indent+1); + sb.append("RIGHT SIDE DEF: "); + if (getRightSideDefinition() != null) { + sb.append(getRightSideDefinition().toString()); + } else { + sb.append("null"); + } + } + QName matchingRule = getMatchingRule(); if (matchingRule != null) { sb.append("\n"); @@ -369,8 +399,22 @@ public String toString(StringBuilder sb){ } } } + if (rightSidePath != null) { + sb.append(getRightSidePath()); + } return sb.toString(); } + // TODO cleanup this mess - how values are cloned, that expression is not cloned in LT/GT filter etc + public abstract PropertyValueFilter clone(); + + protected void copyRightSideThingsFrom(PropertyValueFilter original) { + if (original.getRightSidePath() != null) { + setRightSidePath(original.getRightSidePath()); + } + if (original.getRightSideDefinition() != null) { + setRightSideDefinition(original.getRightSideDefinition()); + } + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java index 77c9164cb24..97e89fdf43e 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/RefFilter.java @@ -138,7 +138,7 @@ public static RefFilter createReferenceEqual(QName proper } - private static RefFilter createNullRefFilter(ItemPath path, PrismReferenceDefinition refDef){ + public static RefFilter createNullRefFilter(ItemPath path, PrismReferenceDefinition refDef){ return new RefFilter(path, refDef, null, null); } @@ -237,6 +237,4 @@ public PrismReferenceDefinition getDefinition() { // TODO Auto-generated method stub return (PrismReferenceDefinition) super.getDefinition(); } - - } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java index d3c12bc9bd8..d3ce0de032f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java @@ -64,12 +64,12 @@ public static S_FilterEntryOrEmpty queryFor(Class query return R_Filter.create(builder); } - ItemDefinition findItemDefinition(ItemPath itemPath) throws SchemaException { - ItemDefinition itemDefinition = containerCTD.findItemDefinition(itemPath); - if (itemDefinition == null) { - throw new SchemaException("Couldn't find definition for '" + itemPath + "' in " + containerCTD); - } - return itemDefinition; - } +// ItemDefinition findItemDefinition(ItemPath itemPath) throws SchemaException { +// ItemDefinition itemDefinition = containerCTD.findItemDefinition(itemPath); +// if (itemDefinition == null) { +// throw new SchemaException("Couldn't find definition for '" + itemPath + "' in " + containerCTD); +// } +// return itemDefinition; +// } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java index 2f189bc9b68..f812ede3631 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_AtomicFilter.java @@ -29,10 +29,11 @@ import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.GreaterFilter; import com.evolveum.midpoint.prism.query.LessFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.PropertyValueFilter; +import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; -import com.evolveum.midpoint.prism.query.ValueFilter; import com.evolveum.midpoint.util.exception.SchemaException; import org.apache.commons.lang.Validate; @@ -41,15 +42,16 @@ /** * @author mederly */ -public class R_AtomicFilter implements S_ConditionEntry, S_MatchingRuleEntry { +public class R_AtomicFilter implements S_ConditionEntry, S_MatchingRuleEntry, S_RightHandItemEntry { final ItemPath itemPath; final PrismPropertyDefinition propertyDefinition; final PrismReferenceDefinition referenceDefinition; final PropertyValueFilter filter; final R_Filter owner; + final boolean expectingRightSide; - public R_AtomicFilter(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { + R_AtomicFilter(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { Validate.notNull(itemPath); Validate.notNull(itemDefinition); Validate.notNull(owner); @@ -65,9 +67,10 @@ public R_AtomicFilter(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter } this.filter = null; this.owner = owner; + this.expectingRightSide = false; } - public R_AtomicFilter(R_AtomicFilter original, PropertyValueFilter filter) { + R_AtomicFilter(R_AtomicFilter original, PropertyValueFilter filter, boolean expectingRightSide) { Validate.notNull(original); Validate.notNull(filter); this.itemPath = original.itemPath; @@ -75,26 +78,49 @@ public R_AtomicFilter(R_AtomicFilter original, PropertyValueFilter filter) { this.referenceDefinition = original.referenceDefinition; this.filter = filter; this.owner = original.owner; + this.expectingRightSide = expectingRightSide; + } + + public R_AtomicFilter(R_AtomicFilter original, PropertyValueFilter filter) { + this(original, filter, false); } static R_AtomicFilter create(ItemPath itemPath, ItemDefinition itemDefinition, R_Filter owner) { return new R_AtomicFilter(itemPath, itemDefinition, owner); } + @Override + public S_AtomicFilterExit item(QName... names) throws SchemaException { + return item(new ItemPath(names), null); + } + + @Override + public S_AtomicFilterExit item(ItemPath itemPath, ItemDefinition itemDefinition) throws SchemaException { + if (!expectingRightSide) { + throw new IllegalStateException("Unexpected item() call"); + } + if (filter == null) { + throw new IllegalStateException("item() call with no filter"); + } + PropertyValueFilter newFilter = filter.clone(); + newFilter.setRightSidePath(itemPath); + newFilter.setRightSideDefinition(itemDefinition); + return new R_AtomicFilter(this, newFilter); + } + @Override public S_MatchingRuleEntry eq(Object value) { return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, value)); } @Override - public S_MatchingRuleEntry eqPoly(String orig, String norm) { - return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, new PolyString(orig, norm))); + public S_RightHandItemEntry eq() { + return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, (Object) null), true); } @Override - public S_MatchingRuleEntry eqItem(QName... names) { - ItemPath rightSidePath = new ItemPath(names); - return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, rightSidePath, null)); + public S_MatchingRuleEntry eqPoly(String orig, String norm) { + return new R_AtomicFilter(this, EqualFilter.createEqual(itemPath, propertyDefinition, null, new PolyString(orig, norm))); } @Override @@ -103,9 +129,8 @@ public S_MatchingRuleEntry gt(Object value) throws SchemaException { } @Override - public S_MatchingRuleEntry gtItem(QName... names) throws SchemaException { - ItemPath rightSidePath = new ItemPath(names); - return new R_AtomicFilter(this, GreaterFilter.createGreaterThanItem(itemPath, propertyDefinition, rightSidePath, null, false)); + public S_RightHandItemEntry gt() { + return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, null, false), true); } @Override @@ -114,9 +139,8 @@ public S_MatchingRuleEntry ge(Object value) throws SchemaException { } @Override - public S_MatchingRuleEntry geItem(QName... names) { - ItemPath rightSidePath = new ItemPath(names); - return new R_AtomicFilter(this, GreaterFilter.createGreaterThanItem(itemPath, propertyDefinition, rightSidePath, null, true)); + public S_RightHandItemEntry ge() { + return new R_AtomicFilter(this, GreaterFilter.createGreater(itemPath, propertyDefinition, null, true), true); } @Override @@ -125,9 +149,8 @@ public S_MatchingRuleEntry lt(Object value) throws SchemaException { } @Override - public S_MatchingRuleEntry ltItem(QName... names) { - ItemPath rightSidePath = new ItemPath(names); - return new R_AtomicFilter(this, LessFilter.createLessThanItem(itemPath, propertyDefinition, rightSidePath, null, false)); + public S_RightHandItemEntry lt() { + return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, null, false), true); } @Override @@ -136,9 +159,8 @@ public S_MatchingRuleEntry le(Object value) throws SchemaException { } @Override - public S_MatchingRuleEntry leItem(QName... names) { - ItemPath rightSidePath = new ItemPath(names); - return new R_AtomicFilter(this, LessFilter.createLessThanItem(itemPath, propertyDefinition, rightSidePath, null, true)); + public S_RightHandItemEntry le() { + return new R_AtomicFilter(this, LessFilter.createLess(itemPath, propertyDefinition, null, true), true); } @Override @@ -158,17 +180,28 @@ public S_MatchingRuleEntry contains(String value) { @Override public S_AtomicFilterExit ref(PrismReferenceValue value) { - throw new UnsupportedOperationException(); + return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, value)); } @Override public S_AtomicFilterExit ref(String oid) { - throw new UnsupportedOperationException(); + return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, oid)); + } + + @Override + public S_AtomicFilterExit ref(String oid, QName targetTypeName) { + return ref(new PrismReferenceValue(oid, targetTypeName)); } @Override public S_AtomicFilterExit isNull() { - throw new UnsupportedOperationException(); + if (propertyDefinition != null) { + return new R_AtomicFilter(this, EqualFilter.createNullEqual(itemPath, propertyDefinition, null)); + } else if (referenceDefinition != null) { + return new R_AtomicFilter(this, RefFilter.createNullRefFilter(itemPath, referenceDefinition)); + } else { + throw new IllegalStateException("No definition"); + } } @Override @@ -217,12 +250,17 @@ public ObjectQuery build() throws SchemaException { } @Override - public S_QueryExit asc(QName... names) throws SchemaException { + public ObjectFilter buildFilter() throws SchemaException { + return build().getFilter(); + } + + @Override + public S_FilterExit asc(QName... names) throws SchemaException { return finish().asc(names); } @Override - public S_QueryExit desc(QName... names) throws SchemaException { + public S_FilterExit desc(QName... names) throws SchemaException { return finish().desc(names); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java index df29c54bf68..434ec8a8611 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.prism.ComplexTypeDefinition; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.AllFilter; @@ -27,13 +28,19 @@ import com.evolveum.midpoint.prism.query.NoneFilter; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectOrdering; +import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.prism.query.OrderDirection; import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.prism.query.UndefinedFilter; import com.evolveum.midpoint.util.exception.SchemaException; +import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.List; /** * EXPERIMENTAL IMPLEMENTATION. @@ -43,32 +50,42 @@ public class R_Filter implements S_FilterEntryOrEmpty, S_AtomicFilterExit { final private QueryBuilder queryBuilder; + final private Class currentClass; // object we are working on (changes on Exists filter) final private OrFilter currentFilter; final private LogicalSymbol lastLogicalSymbol; final private boolean isNegated; final private R_Filter parentFilter; final private QName typeRestriction; final private ItemPath existsRestriction; + final private List orderingList; public R_Filter(QueryBuilder queryBuilder) { this.queryBuilder = queryBuilder; + this.currentClass = queryBuilder.getQueryClass(); this.currentFilter = OrFilter.createOr(); this.lastLogicalSymbol = null; this.isNegated = false; this.parentFilter = null; this.typeRestriction = null; this.existsRestriction = null; + this.orderingList = new ArrayList<>(); } - private R_Filter(QueryBuilder queryBuilder, OrFilter currentFilter, LogicalSymbol lastLogicalSymbol, - boolean isNegated, R_Filter parentFilter, QName typeRestriction, ItemPath existsRestriction) { + private R_Filter(QueryBuilder queryBuilder, Class currentClass, OrFilter currentFilter, LogicalSymbol lastLogicalSymbol, + boolean isNegated, R_Filter parentFilter, QName typeRestriction, ItemPath existsRestriction, List orderingList) { this.queryBuilder = queryBuilder; + this.currentClass = currentClass; this.currentFilter = currentFilter; this.lastLogicalSymbol = lastLogicalSymbol; this.isNegated = isNegated; this.parentFilter = parentFilter; this.typeRestriction = typeRestriction; this.existsRestriction = existsRestriction; + if (orderingList != null) { + this.orderingList = orderingList; + } else { + this.orderingList = new ArrayList<>(); + } } public static S_FilterEntryOrEmpty create(QueryBuilder builder) { @@ -101,12 +118,12 @@ R_Filter addSubfilter(ObjectFilter subfilter) throws SchemaException { return parentFilter.addSubfilter( ExistsFilter.createExists( existsRestriction, - queryBuilder.getQueryClass(), + parentFilter.currentClass, queryBuilder.getPrismContext(), subfilter)); } else { OrFilter newFilter = appendAtomicFilter(subfilter, isNegated, lastLogicalSymbol); - return new R_Filter(queryBuilder, newFilter, null, false, parentFilter, typeRestriction, existsRestriction); + return new R_Filter(queryBuilder, currentClass, newFilter, null, false, parentFilter, typeRestriction, existsRestriction, orderingList); } } @@ -129,14 +146,21 @@ private R_Filter setLastLogicalSymbol(LogicalSymbol newLogicalSymbol) { if (this.lastLogicalSymbol != null) { throw new IllegalStateException("Two logical symbols in a sequence"); } - return new R_Filter(queryBuilder, currentFilter, newLogicalSymbol, isNegated, parentFilter, typeRestriction, existsRestriction); + return new R_Filter(queryBuilder, currentClass, currentFilter, newLogicalSymbol, isNegated, parentFilter, typeRestriction, existsRestriction, orderingList); } private R_Filter setNegated() { if (isNegated) { throw new IllegalStateException("Double negation"); } - return new R_Filter(queryBuilder, currentFilter, lastLogicalSymbol, true, parentFilter, typeRestriction, existsRestriction); + return new R_Filter(queryBuilder, currentClass, currentFilter, lastLogicalSymbol, true, parentFilter, typeRestriction, existsRestriction, orderingList); + } + + private R_Filter addOrdering(ObjectOrdering ordering) { + Validate.notNull(ordering); + List newList = new ArrayList<>(orderingList); + newList.add(ordering); + return new R_Filter(queryBuilder, currentClass, currentFilter, lastLogicalSymbol, isNegated, parentFilter, typeRestriction, existsRestriction, newList); } @Override @@ -202,7 +226,7 @@ public S_AtomicFilterExit isRoot() { @Override public S_FilterEntryOrEmpty block() { - return new R_Filter(queryBuilder, OrFilter.createOr(), null, false, this, null, null); + return new R_Filter(queryBuilder, currentClass, OrFilter.createOr(), null, false, this, null, null, null); } @Override @@ -215,16 +239,37 @@ public S_FilterEntry type(Class type) throws SchemaExce if (typeName == null) { throw new IllegalStateException("No type name for " + ctd); } - return new R_Filter(queryBuilder, OrFilter.createOr(), null, false, this, typeName, null); + return new R_Filter(queryBuilder, type, OrFilter.createOr(), null, false, this, typeName, null, null); } @Override - public S_FilterEntry exists(QName... names) { + public S_FilterEntry exists(QName... names) throws SchemaException { if (existsRestriction != null) { throw new IllegalStateException("Exists within exists"); } + if (names.length == 0) { + throw new SchemaException("Empty path in exists() filter is not allowed."); + } ItemPath existsPath = new ItemPath(names); - return new R_Filter(queryBuilder, OrFilter.createOr(), null, false, this, null, existsPath); + PrismContainerDefinition pcd = resolveItemPath(existsPath, PrismContainerDefinition.class); + Class clazz = pcd.getCompileTimeClass(); + if (clazz == null) { + throw new SchemaException("Item path of '" + existsPath + "' in " + currentClass + " does not point to a valid prism container."); + } + return new R_Filter(queryBuilder, clazz, OrFilter.createOr(), null, false, this, null, existsPath, null); + } + + ID resolveItemPath(ItemPath itemPath, Class type) throws SchemaException { + Validate.notNull(type, "type"); + ComplexTypeDefinition ctd = queryBuilder.getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(currentClass); + if (ctd == null) { + throw new SchemaException("Definition for " + currentClass + " couldn't be found."); + } + ID definition = ctd.findItemDefinition(itemPath, type); + if (definition == null) { + throw new SchemaException("Item path of '" + itemPath + "' in " + currentClass + " does not point to a valid " + type.getSimpleName()); + } + return definition; } // END OF TODO ............................................. @@ -247,7 +292,12 @@ public S_AtomicFilterEntry not() { @Override public S_ConditionEntry item(QName... names) throws SchemaException { ItemPath itemPath = new ItemPath(names); - ItemDefinition itemDefinition = queryBuilder.findItemDefinition(itemPath); + ItemDefinition itemDefinition = resolveItemPath(itemPath, ItemDefinition.class); + return item(itemPath, itemDefinition); + } + + @Override + public S_ConditionEntry item(ItemPath itemPath, ItemDefinition itemDefinition) throws SchemaException { return R_AtomicFilter.create(itemPath, itemDefinition, this); } @@ -270,13 +320,19 @@ private boolean hasRestriction() { } @Override - public S_QueryExit asc(QName... names) { - throw new UnsupportedOperationException(); + public S_FilterExit asc(QName... names) throws SchemaException { + if (names.length == 0) { + throw new SchemaException("There must be at least one name for asc(...) ordering"); + } + return addOrdering(ObjectOrdering.createOrdering(new ItemPath(names), OrderDirection.ASCENDING)); } @Override - public S_QueryExit desc(QName... names) { - throw new UnsupportedOperationException(); + public S_FilterExit desc(QName... names) throws SchemaException { + if (names.length == 0) { + throw new SchemaException("There must be at least one name for asc(...) ordering"); + } + return addOrdering(ObjectOrdering.createOrdering(new ItemPath(names), OrderDirection.DESCENDING)); } @Override @@ -288,7 +344,19 @@ public ObjectQuery build() throws SchemaException { if (parentFilter != null) { throw new SchemaException("A block in filter definition was probably not closed."); } - return ObjectQuery.createObjectQuery(simplify(currentFilter)); + ObjectPaging paging; + if (!orderingList.isEmpty()) { + paging = ObjectPaging.createEmptyPaging(); + paging.setOrdering(orderingList); + } else { + paging = null; + } + return ObjectQuery.createObjectQuery(simplify(currentFilter), paging); + } + + @Override + public ObjectFilter buildFilter() throws SchemaException { + return build().getFilter(); } private ObjectFilter simplify(OrFilter filter) { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java index 9fef393a031..4e617238873 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java @@ -17,7 +17,9 @@ package com.evolveum.midpoint.prism.query.builder; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.exception.SchemaException; import javax.xml.namespace.QName; @@ -30,6 +32,7 @@ public interface S_AtomicFilterEntry { S_AtomicFilterExit none() throws SchemaException; S_AtomicFilterExit undefined() throws SchemaException; S_ConditionEntry item(QName... names) throws SchemaException; + S_ConditionEntry item(ItemPath itemPath, ItemDefinition itemDefinition) throws SchemaException; S_AtomicFilterExit id(String... identifiers); S_AtomicFilterExit id(long... identifiers); S_AtomicFilterExit ownerId(String... identifiers); @@ -41,5 +44,5 @@ public interface S_AtomicFilterEntry { S_AtomicFilterExit isRoot(); S_FilterEntryOrEmpty block(); S_FilterEntry type(Class type) throws SchemaException; - S_FilterEntry exists(QName... names); + S_FilterEntry exists(QName... names) throws SchemaException; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java index d6a68c5f616..2913b0c499e 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_ConditionEntry.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.prism.query.builder; import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.util.exception.SchemaException; @@ -28,20 +29,22 @@ */ public interface S_ConditionEntry { S_MatchingRuleEntry eq(Object value); + S_RightHandItemEntry eq(); S_MatchingRuleEntry eqPoly(String orig, String norm); - S_MatchingRuleEntry eqItem(QName... value); S_MatchingRuleEntry gt(Object value) throws SchemaException; - S_MatchingRuleEntry gtItem(QName... names) throws SchemaException; + S_RightHandItemEntry gt(); S_MatchingRuleEntry ge(Object value) throws SchemaException; - S_MatchingRuleEntry geItem(QName... names); + S_RightHandItemEntry ge(); S_MatchingRuleEntry lt(Object value) throws SchemaException; - S_MatchingRuleEntry ltItem(QName... names); + S_RightHandItemEntry lt(); S_MatchingRuleEntry le(Object value) throws SchemaException; - S_MatchingRuleEntry leItem(QName... names); + S_RightHandItemEntry le(); S_AtomicFilterExit startsWith(String value); S_AtomicFilterExit endsWith(String value); S_AtomicFilterExit contains(String value); S_AtomicFilterExit ref(PrismReferenceValue value); S_AtomicFilterExit ref(String oid); + S_AtomicFilterExit ref(String oid, QName targetTypeName); S_AtomicFilterExit isNull(); + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java index 57486898910..a45087d9dbe 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_FilterExit.java @@ -28,6 +28,6 @@ public interface S_FilterExit extends S_QueryExit { S_AtomicFilterExit endBlock() throws SchemaException; - S_QueryExit asc(QName... names) throws SchemaException; - S_QueryExit desc(QName... names) throws SchemaException; + S_FilterExit asc(QName... names) throws SchemaException; + S_FilterExit desc(QName... names) throws SchemaException; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java index 1b90f6be653..650076413a3 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_QueryExit.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.prism.query.builder; +import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.util.exception.SchemaException; @@ -25,5 +26,6 @@ public interface S_QueryExit { ObjectQuery build() throws SchemaException; + ObjectFilter buildFilter() throws SchemaException; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_RightHandItemEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_RightHandItemEntry.java new file mode 100644 index 00000000000..c9a8a8a0edc --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_RightHandItemEntry.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.query.builder; + +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; + +/** + * @author mederly + */ +public interface S_RightHandItemEntry { + // TODO add support for matching rules + S_AtomicFilterExit item(QName... names) throws SchemaException; + S_AtomicFilterExit item(ItemPath itemPath, ItemDefinition itemDefinition) throws SchemaException; +} diff --git a/infra/prism/src/main/resources/xml/ns/test/foo-1.xsd b/infra/prism/src/main/resources/xml/ns/test/foo-1.xsd index 557811533eb..0980762a9ad 100644 --- a/infra/prism/src/main/resources/xml/ns/test/foo-1.xsd +++ b/infra/prism/src/main/resources/xml/ns/test/foo-1.xsd @@ -291,6 +291,7 @@ + diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestPrismContext.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestPrismContext.java index 92471ad0b5c..cf46595af95 100644 --- a/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestPrismContext.java +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestPrismContext.java @@ -191,7 +191,7 @@ private void assertUserDefinition(PrismObjectDefinition userDefinition PrismAsserts.assertDefinition(assignmentContainer, USER_ASSIGNMENT_QNAME, ASSIGNMENT_TYPE_QNAME, 0, -1); assertFalse("Assignment is runtime", assignmentContainer.isRuntimeSchema()); assertEquals("Wrong compile time class for assignment container", AssignmentType.class, assignmentContainer.getCompileTimeClass()); - assertEquals("Assignment size", 3, assignmentContainer.getDefinitions().size()); + assertEquals("Assignment size", 4, assignmentContainer.getDefinitions().size()); PrismAsserts.assertPropertyDefinition(assignmentContainer, USER_DESCRIPTION_QNAME, DOMUtil.XSD_STRING, 0, 1); PrismAsserts.assertPropertyDefinition(assignmentContainer, USER_ACCOUNT_CONSTRUCTION_QNAME, ACCOUNT_CONSTRUCTION_TYPE_QNAME, 0, 1); diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/AssignmentType.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/AssignmentType.java index c653a9974e3..6eabcaf2d20 100644 --- a/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/AssignmentType.java +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/AssignmentType.java @@ -59,6 +59,7 @@ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AssignmentType", propOrder = { "description", + "note", "accountConstruction" }) public class AssignmentType @@ -67,11 +68,13 @@ public class AssignmentType // This is NOT GENERATED. It is supplied here manually for the testing. public final static QName F_DESCRIPTION = new QName(ObjectType.NS_FOO, "description"); + public final static QName F_NOTE = new QName(ObjectType.NS_FOO, "note"); public final static QName F_ACCOUNT_CONSTRUCTION = new QName(ObjectType.NS_FOO, "accountConstruction"); public final static QName F_ACTIVATION = new QName(ObjectType.NS_FOO, "activation"); private final static long serialVersionUID = 201202081233L; protected String description; + protected String note; protected AccountConstructionType accountConstruction; @XmlAttribute(name = "id") protected String id; @@ -100,6 +103,14 @@ public void setDescription(String value) { this.description = value; } + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + /** * Gets the value of the accountConstruction property. * diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/ObjectFactory.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/ObjectFactory.java index 169a4c9da01..fa6a852ae78 100644 --- a/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/ObjectFactory.java +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/foo/ObjectFactory.java @@ -49,6 +49,7 @@ public class ObjectFactory { private final static QName _DisplayName_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd", "displayName"); private final static QName _Account_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd", "account"); private final static QName _Description_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd", "description"); + private final static QName _Note_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd", "note"); private final static QName _StatusFilter_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/public/common/common-3", "statusFilter"); private final static QName _CategoryFilter_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/public/common/common-3", "categoryFilter"); private final static QName _OperationFilter_QNAME = new QName("http://midpoint.evolveum.com/xml/ns/public/common/common-3", "operationFilter"); diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java index 332aa18c891..4fa7789cb64 100644 --- a/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestQueryBuilder.java @@ -16,15 +16,22 @@ package com.evolveum.midpoint.prism.query; +import com.evolveum.midpoint.prism.ComplexTypeDefinition; +import com.evolveum.midpoint.prism.PrismConstants; +import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismInternalTestUtil; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.foo.AssignmentType; import com.evolveum.midpoint.prism.foo.UserType; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.match.MatchingRuleRegistryFactory; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.SchemaException; +import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIConversion; import org.testng.AssertJUnit; import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeSuite; @@ -38,10 +45,14 @@ import static com.evolveum.midpoint.prism.PrismInternalTestUtil.DEFAULT_NAMESPACE_PREFIX; import static com.evolveum.midpoint.prism.PrismInternalTestUtil.NS_FOO; import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext; +import static com.evolveum.midpoint.prism.util.PrismTestUtil.getSchemaRegistry; /** * Here are the most simple tests for Query Builder. * More advanced tests are part of QueryInterpreterTest in repo-sql-impl-test. + * + * These tests are strict in the sense they check the exact structure of created queries. + * Repo tests check just the HQL outcome. */ public class TestQueryBuilder { @@ -91,7 +102,7 @@ public void test112EmptyBlocks() throws Exception{ } @Test(expectedExceptions = SchemaException.class) - public void test112BlocksLeftOpen() throws Exception{ + public void test113BlocksLeftOpen() throws Exception{ QueryBuilder.queryFor(UserType.class, getPrismContext()) .block() .block() @@ -218,7 +229,7 @@ public void test142TypeWithEqualsInBlock() throws Exception{ ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) .type(UserType.class) .block() - .item(UserType.F_LOCALITY).eq("Caribbean") + .item(UserType.F_LOCALITY).eq("Caribbean") .endBlock() .build(); ObjectQuery expected = ObjectQuery.createObjectQuery( @@ -235,8 +246,8 @@ public void test144TypeWithEqualsAndAllInBlock() throws Exception{ ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) .type(UserType.class) .block() - .item(UserType.F_LOCALITY).eq("Caribbean") - .and().all() + .item(UserType.F_LOCALITY).eq("Caribbean") + .and().all() .endBlock() .build(); ObjectQuery expected = ObjectQuery.createObjectQuery( @@ -255,9 +266,9 @@ public void test144TypeWithEqualsAndAllInBlock() throws Exception{ public void test144TypeInTypeInType() throws Exception{ ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) .type(UserType.class) - .type(AssignmentType.class) - .type(UserType.class) - .all() + .type(AssignmentType.class) + .type(UserType.class) + .all() .build(); ObjectQuery expected = ObjectQuery.createObjectQuery( TypeFilter.createType( @@ -278,7 +289,7 @@ public void test144TypeInTypeInType() throws Exception{ public void test146TypeAndSomething() throws Exception{ ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) .type(UserType.class) - .none() + .none() .and().all() .build(); ObjectQuery expected = ObjectQuery.createObjectQuery( @@ -312,7 +323,7 @@ public void test148TypeEmpty() throws Exception{ public void test149TypeEmptyAndAll() throws Exception{ ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) .type(UserType.class) - .block().endBlock() + .block().endBlock() .and().all() .build(); ObjectQuery expected = ObjectQuery.createObjectQuery( @@ -327,6 +338,188 @@ public void test149TypeEmptyAndAll() throws Exception{ compare(actual, expected); } + @Test + public void test150ExistsWithEquals() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .exists(UserType.F_ASSIGNMENT) + .item(AssignmentType.F_DESCRIPTION).startsWith("desc1") + .build(); + ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class); + PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class); + ObjectQuery expected = ObjectQuery.createObjectQuery( + ExistsFilter.createExists( + new ItemPath(UserType.F_ASSIGNMENT), + userPcd, + SubstringFilter.createSubstring( + new ItemPath(AssignmentType.F_DESCRIPTION), + assCtd.findPropertyDefinition(AssignmentType.F_DESCRIPTION), + null, "desc1", true, false) + ) + ); + compare(actual, expected); + } + + @Test + public void test151ExistsWithEquals2() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .exists(UserType.F_ASSIGNMENT) + .item(AssignmentType.F_NOTE).endsWith("DONE.") + .build(); + ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class); + PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class); + ObjectQuery expected = ObjectQuery.createObjectQuery( + ExistsFilter.createExists( + new ItemPath(UserType.F_ASSIGNMENT), + userPcd, + SubstringFilter.createSubstring( + new ItemPath(AssignmentType.F_NOTE), + assCtd.findPropertyDefinition(AssignmentType.F_NOTE), + null, "DONE.", false, true) + ) + ); + compare(actual, expected); + } + + @Test + public void test152ExistsWithEqualsInBlock() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .exists(UserType.F_ASSIGNMENT) + .block() + .item(AssignmentType.F_NOTE).endsWith("DONE.") + .endBlock() + .build(); + ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class); + PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class); + ObjectQuery expected = ObjectQuery.createObjectQuery( + ExistsFilter.createExists( + new ItemPath(UserType.F_ASSIGNMENT), + userPcd, + SubstringFilter.createSubstring( + new ItemPath(AssignmentType.F_NOTE), + assCtd.findPropertyDefinition(AssignmentType.F_NOTE), + null, "DONE.", false, true) + ) + ); + compare(actual, expected); + } + + @Test + public void test154ExistsWithEqualsAndAllInBlock() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .exists(UserType.F_ASSIGNMENT) + .block() + .item(AssignmentType.F_NOTE).endsWith("DONE.") + .and().all() + .endBlock() + .build(); + ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class); + PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class); + ObjectQuery expected = ObjectQuery.createObjectQuery( + ExistsFilter.createExists( + new ItemPath(UserType.F_ASSIGNMENT), + userPcd, + AndFilter.createAnd( + SubstringFilter.createSubstring( + new ItemPath(AssignmentType.F_NOTE), + assCtd.findPropertyDefinition(AssignmentType.F_NOTE), + null, "DONE.", false, true + ), + AllFilter.createAll() + ) + ) + ); + compare(actual, expected); + } + + @Test + public void test156ExistsAndSomething() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .exists(UserType.F_ASSIGNMENT) + .none() + .and().all() + .build(); + + ComplexTypeDefinition assCtd = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AssignmentType.class); + PrismContainerDefinition userPcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(UserType.class); + ObjectQuery expected = ObjectQuery.createObjectQuery( + AndFilter.createAnd( + ExistsFilter.createExists( + new ItemPath(UserType.F_ASSIGNMENT), + userPcd, + NoneFilter.createNone() + ), + AllFilter.createAll() + ) + ); + compare(actual, expected); + } + + @Test + public void test200OrderByName() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .asc(UserType.F_NAME) + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + ObjectPaging.createPaging(UserType.F_NAME, OrderDirection.ASCENDING) + ); + compare(actual, expected); + } + + @Test + public void test210OrderByNameAndId() throws Exception{ + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_LOCALITY).eq("Caribbean") + .asc(UserType.F_NAME) + .desc(PrismConstants.T_ID) + .build(); + ObjectPaging paging = ObjectPaging.createEmptyPaging(); + paging.addOrderingInstruction(UserType.F_NAME, OrderDirection.ASCENDING); + paging.addOrderingInstruction(PrismConstants.T_ID, OrderDirection.DESCENDING); + ObjectQuery expected = ObjectQuery.createObjectQuery( + EqualFilter.createEqual(UserType.F_LOCALITY, UserType.class, getPrismContext(), "Caribbean"), + paging); + compare(actual, expected); + } + + @Test + public void test300EqualItem() throws Exception { + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_LOCALITY).eq().item(UserType.F_NAME) + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + EqualFilter.createEqual( + new ItemPath(UserType.F_LOCALITY), + UserType.class, + getPrismContext(), + null, + new ItemPath(UserType.F_NAME), + null + ) + ); + compare(actual, expected); + } + + @Test + public void test310LessThanItem() throws Exception { + PrismObjectDefinition userDef = getSchemaRegistry().findObjectDefinitionByCompileTimeClass(UserType.class); + PrismPropertyDefinition nameDef = userDef.findPropertyDefinition(UserType.F_NAME); + PrismPropertyDefinition localityDef = userDef.findPropertyDefinition(UserType.F_LOCALITY); + ObjectQuery actual = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(new ItemPath(UserType.F_LOCALITY), localityDef) + .le() + .item(new ItemPath(UserType.F_NAME), nameDef) + .build(); + ObjectQuery expected = ObjectQuery.createObjectQuery( + LessFilter.createLessThanItem( + new ItemPath(UserType.F_LOCALITY), + localityDef, + new ItemPath(UserType.F_NAME), + nameDef, + true + ) + ); + compare(actual, expected); + } protected void compare(ObjectQuery actual, ObjectQuery expected) { String exp = expected.debugDump(); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java index dce2c61da05..0af57896d96 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java @@ -35,7 +35,7 @@ public class CertCampaignTypeUtil { public static AccessCertificationStageType getCurrentStage(AccessCertificationCampaignType campaign) { for (AccessCertificationStageType stage : campaign.getStage()) { - if (stage.getNumber() == campaign.getCurrentStageNumber()) { + if (stage.getNumber() == campaign.getStageNumber()) { return stage; } } @@ -99,7 +99,7 @@ public static boolean isRemediationAutomatic(AccessCertificationCampaignType cam } public static boolean isCampaignClosed(AccessCertificationCampaignType campaign) { - int currentStage = campaign.getCurrentStageNumber(); + int currentStage = campaign.getStageNumber(); int stages = getNumberOfStages(campaign); return AccessCertificationCampaignStateType.CLOSED.equals(campaign.getState()) || currentStage > stages; } @@ -128,6 +128,6 @@ public static void checkStageDefinitionConsistency(List - + The stage this campaign is in. @@ -12717,12 +12717,16 @@ - + - The number of current stage to which the "currentResponse" relates to. - If the case is not transferred into the next stage, the value of this item stays to be set as it is - - indicating the last stage this case took part in. + The number of current stage in which this case is. + E.g. currentResponse relates to the currentStage. + Case is "enabled" for a current campaign stage if and only if case.currentStage == campaign.stageNumber. + + When opening a campaign stage, case's currentStage either advances (if it is transferred to stage being opened) + or stays at the existing value (if it is not). It then indicates the last stage this case + took part of. @@ -12733,14 +12737,14 @@ --> - - - - Is the case enabled for the current stage? E.g. cases that have been marked as "remove" in a given stage - may be disabled for later stages. - - - + + + + + + + + diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java index bff0eb39852..819d1106f66 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertEventHelper.java @@ -95,10 +95,10 @@ public void onReviewDeadlineApproaching(ObjectReferenceType reviewerRef, List getCurrentReviewers(List caseList) { + public Collection getCurrentReviewers(AccessCertificationCampaignType campaign, List caseList) { Set oids = new HashSet<>(); for (AccessCertificationCaseType aCase : caseList) { - if (Boolean.TRUE.equals(aCase.isEnabled())) { + if (aCase.getCurrentStageNumber() == campaign.getStageNumber()) { for (ObjectReferenceType reviewerRef : aCase.getReviewerRef()) { oids.add(reviewerRef.getOid()); } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java index 0d64e07de6a..732f29f61ec 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java @@ -163,7 +163,7 @@ AccessCertificationCampaignType createCampaignObject(AccessCertificationDefiniti newCampaign.setStart(null); newCampaign.setEnd(null); newCampaign.setState(CREATED); - newCampaign.setCurrentStageNumber(0); + newCampaign.setStageNumber(0); return newCampaign; } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java index a7a8c928841..81220e65954 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java @@ -20,10 +20,19 @@ import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.prism.query.*; +import com.evolveum.midpoint.prism.query.AndFilter; +import com.evolveum.midpoint.prism.query.InOidFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectOrdering; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; @@ -45,12 +54,28 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import javax.xml.namespace.QName; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static com.evolveum.midpoint.prism.PrismConstants.T_PARENT; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REVIEW_STAGE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_STATE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CURRENT_STAGE_NUMBER; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_DECISION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_REVIEWER_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_STAGE_NUMBER; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; /** * @author mederly @@ -103,13 +128,19 @@ protected List searchCases(String campaignOid, Obje * objectRef -> objectRef/@/name * campaignRef -> ../name * + * Plus adds ID as secondary criteria, in order to avoid random shuffling the result set. + * * Temporary solution - until we implement that in GUI. */ private ObjectQuery hackPaging(ObjectQuery query) { - if (query.getPaging() == null || ItemPath.isNullOrEmpty(query.getPaging().getOrderBy())) { + if (query.getPaging() == null || !query.getPaging().hasOrdering()) { + return query; + } + if (query.getPaging().getOrderingInstructions().size() > 1) { return query; } ItemPath oldPath = query.getPaging().getOrderBy(); + OrderDirection oldDirection = query.getPaging().getDirection(); if (oldPath.size() != 1 || !(oldPath.first() instanceof NameItemPathSegment)) { return query; } @@ -120,12 +151,14 @@ private ObjectQuery hackPaging(ObjectQuery query) { } else if (QNameUtil.match(oldName, AccessCertificationCaseType.F_OBJECT_REF)) { newPath = new ItemPath(AccessCertificationCaseType.F_OBJECT_REF, PrismConstants.T_OBJECT_REFERENCE, ObjectType.F_NAME); } else if (QNameUtil.match(oldName, AccessCertificationCaseType.F_CAMPAIGN_REF)) { - newPath = new ItemPath(PrismConstants.T_PARENT, ObjectType.F_NAME); + newPath = new ItemPath(T_PARENT, ObjectType.F_NAME); } else { - return query; + newPath = oldPath; } ObjectPaging paging1 = query.getPaging().clone(); - paging1.setOrderBy(newPath); + ObjectOrdering primary = ObjectOrdering.createOrdering(newPath, oldDirection); + ObjectOrdering secondary = ObjectOrdering.createOrdering(new ItemPath(PrismConstants.T_ID), OrderDirection.ASCENDING); // to avoid random shuffling if first criteria is too vague + paging1.setOrdering(primary, secondary); ObjectQuery query1 = query.clone(); query1.setPaging(paging1); return query1; @@ -133,25 +166,49 @@ private ObjectQuery hackPaging(ObjectQuery query) { protected List searchDecisions(ObjectQuery query, String reviewerOid, boolean notDecidedOnly, Collection> options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException { - // TODO FILTER BY NOT_DECIDED_ONLY - // enhance filter with reviewerRef + enabled ObjectQuery newQuery; - ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); - ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( - new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), - AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); - ObjectFilter enabledFilter = EqualFilter.createEqual( - AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); - ObjectFilter reviewerAndEnabledFilter = AndFilter.createAnd(reviewerFilter, enabledFilter); + + PrismReferenceValue reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER).asReferenceValue(); + ObjectFilter reviewerAndEnabledFilter = getReviewerAndEnabledFilter(reviewerOid); + + ObjectFilter filterToAdd; + if (notDecidedOnly) { + /* + * This filter is intended to return all cases that do not have a decision for a current stage. + * + * Unfortunately, what it really says is "return all cases that have a NULL or NO_RESPONSE decision + * for a current stage. In order to write original filter we'd need to have NOT EXISTS filter + * that would probably require using nested SELECTs (that is not possible now, and overall, it is + * questionable from the point of view of performance). + * + * So, until it's fixed, we assume that on stage opening, NULL decisions are created for all + * cases and all reviewers. + */ + ObjectFilter noResponseFilter = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .exists(F_DECISION) + .block() + .item(AccessCertificationDecisionType.F_REVIEWER_REF).ref(reviewerRef) + .and().item(F_STAGE_NUMBER).eq().item(T_PARENT, F_CURRENT_STAGE_NUMBER) + .and().block() + .item(F_RESPONSE).eq(NO_RESPONSE) + .or().item(F_RESPONSE).isNull() + .endBlock() + .endBlock() + .buildFilter(); + filterToAdd = AndFilter.createAnd(reviewerAndEnabledFilter, noResponseFilter); + } else { + filterToAdd = reviewerAndEnabledFilter; + } + if (query == null) { - newQuery = ObjectQuery.createObjectQuery(reviewerAndEnabledFilter); + newQuery = ObjectQuery.createObjectQuery(filterToAdd); } else { newQuery = query.clone(); if (query.getFilter() == null) { - newQuery.setFilter(reviewerAndEnabledFilter); + newQuery.setFilter(filterToAdd); } else { - newQuery.setFilter(AndFilter.createAnd(query.getFilter(), reviewerAndEnabledFilter)); + newQuery.setFilter(AndFilter.createAnd(query.getFilter(), filterToAdd)); } } @@ -177,7 +234,7 @@ protected List searchDecisions(ObjectQuery query, S campaigns.put(campaignOid, campaign); } - int stage = campaign.getCurrentStageNumber(); + int stage = campaign.getStageNumber(); Iterator decisionIterator = _case.getDecision().iterator(); while (decisionIterator.hasNext()) { AccessCertificationDecisionType decision = decisionIterator.next(); @@ -195,6 +252,20 @@ protected List searchDecisions(ObjectQuery query, S return caseList; } + private ObjectFilter getReviewerAndEnabledFilter(String reviewerOid) throws SchemaException { + // we have to find definition ourselves, as ../state cannot be currently resolved by query builder + ItemPath statePath = new ItemPath(T_PARENT, F_STATE); + PrismPropertyDefinition stateDef = + prismContext.getSchemaRegistry() + .findComplexTypeDefinitionByCompileTimeClass(AccessCertificationCampaignType.class) + .findPropertyDefinition(F_STATE); + return QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .item(F_REVIEWER_REF).ref(reviewerOid, UserType.COMPLEX_TYPE) + .and().item(F_CURRENT_STAGE_NUMBER).eq().item(T_PARENT, AccessCertificationCampaignType.F_STAGE_NUMBER) + .and().item(statePath, stateDef).eq(IN_REVIEW_STAGE) + .buildFilter(); + } + // we expect that only one decision item (the relevant one) is present private boolean isDecided(AccessCertificationCaseType _case) { if (_case.getDecision() == null || _case.getDecision().isEmpty()) { @@ -204,24 +275,14 @@ private boolean isDecided(AccessCertificationCaseType _case) { throw new IllegalStateException("More than 1 decision in case"); } AccessCertificationResponseType response = _case.getDecision().get(0).getResponse(); - return response != null && response != AccessCertificationResponseType.NO_RESPONSE; + return response != null && response != NO_RESPONSE; } public List getCasesForReviewer(AccessCertificationCampaignType campaign, String reviewerOid, Task task, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException { - ObjectFilter filter = AndFilter.createAnd( - RefFilter.createReferenceEqual( - new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), - AccessCertificationCaseType.class, - prismContext, - ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER).asReferenceValue()), - EqualFilter.createEqual( - new ItemPath(AccessCertificationCaseType.F_ENABLED), - AccessCertificationCaseType.class, - prismContext, - true) - ); + + ObjectFilter filter = getReviewerAndEnabledFilter(reviewerOid); List caseList = searchCases(campaign.getOid(), ObjectQuery.createObjectQuery(filter), null, task, result); return caseList; @@ -244,10 +305,11 @@ public AccessCertificationCaseType getCase(String campaignOid, long caseId, Oper } } - public List selectCasesForReviewer(List caseList, String reviewerOid) { + public List selectCasesForReviewer(AccessCertificationCampaignType campaign, List caseList, String reviewerOid) { + List rv = new ArrayList<>(); for (AccessCertificationCaseType aCase : caseList) { - if (Boolean.TRUE.equals(aCase.isEnabled())) { + if (aCase.getCurrentStageNumber() == campaign.getStageNumber()) { for (ObjectReferenceType reviewerRef : aCase.getReviewerRef()) { if (reviewerOid.equals(reviewerRef.getOid())) { rv.add(aCase.clone()); diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertResponseComputationHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertResponseComputationHelper.java index efd0dbab87f..ccb2f5ef6fd 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertResponseComputationHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertResponseComputationHelper.java @@ -43,8 +43,8 @@ public class AccCertResponseComputationHelper { // should be the case enabled in the following stage? - public boolean computeEnabled(AccessCertificationCaseType _case) { - if (!Boolean.TRUE.equals(_case.isEnabled())) { + public boolean computeEnabled(AccessCertificationCampaignType campaign, AccessCertificationCaseType _case) { + if (_case.getCurrentStageNumber() != campaign.getStageNumber()) { return false; } if (_case.getCurrentResponse() == null) { @@ -63,18 +63,18 @@ public boolean computeEnabled(AccessCertificationCaseType _case) { public AccessCertificationResponseType computeResponseForStage(AccessCertificationCaseType _case, AccessCertificationDecisionType newDecision, AccessCertificationCampaignType campaign) { - int stageNumber = campaign.getCurrentStageNumber(); + int stageNumber = campaign.getStageNumber(); List allDecisions = getDecisions(_case, newDecision, stageNumber); return computeResponseForStageInternal(allDecisions, _case, campaign); } public AccessCertificationResponseType computeResponseForStage(AccessCertificationCaseType _case, AccessCertificationCampaignType campaign) { - List allDecisions = getDecisions(_case, campaign.getCurrentStageNumber()); + List allDecisions = getDecisions(_case, campaign.getStageNumber()); return computeResponseForStageInternal(allDecisions, _case, campaign); } private AccessCertificationResponseType computeResponseForStageInternal(List allDecisions, AccessCertificationCaseType _case, AccessCertificationCampaignType campaign) { - int stageNumber = campaign.getCurrentStageNumber(); + int stageNumber = campaign.getStageNumber(); AccessCertificationStageDefinitionType stageDef = CertCampaignTypeUtil.findStageDefinition(campaign, stageNumber); AccessCertificationApprovalStrategyType approvalStrategy = null; if (stageDef != null && stageDef.getReviewerSpecification() != null) { diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java index 5fcf7da54ff..84b4c7d0a62 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java @@ -19,6 +19,7 @@ import com.evolveum.midpoint.certification.impl.handlers.CertificationHandler; import com.evolveum.midpoint.model.api.ModelService; import com.evolveum.midpoint.model.api.PolicyViolationException; +import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; @@ -143,7 +144,7 @@ void recordDecision(AccessCertificationCampaignType campaign, long caseId, Acces decision = decision.clone(); // to not modify the original decision // filling-in missing pieces (if any) - int currentStage = campaign.getCurrentStageNumber(); + int currentStage = campaign.getStageNumber(); if (decision.getStageNumber() == 0) { decision.setStageNumber(currentStage); } else { @@ -163,9 +164,9 @@ void recordDecision(AccessCertificationCampaignType campaign, long caseId, Acces if (_case == null) { throw new ObjectNotFoundException("Case " + caseId + " was not found in campaign " + ObjectTypeUtil.toShortString(campaign)); } - if (!_case.isEnabled()) { - throw new IllegalStateException("Cannot update case because it is not update-enabled in this stage"); - } +// if (!_case.isEnabled()) { +// throw new IllegalStateException("Cannot update case because it is not update-enabled in this stage"); +// } AccessCertificationDecisionType existingDecision = CertCampaignTypeUtil.findDecision(_case, currentStage, decision.getReviewerRef().getOid()); @@ -206,7 +207,7 @@ void recordDecision(AccessCertificationCampaignType campaign, long caseId, Acces } void closeCampaign(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException { - int currentStageNumber = campaign.getCurrentStageNumber(); + int currentStageNumber = campaign.getStageNumber(); int lastStageNumber = CertCampaignTypeUtil.getNumberOfStages(campaign); AccessCertificationCampaignStateType currentState = campaign.getState(); // TODO issue a warning if we are not in a correct state @@ -243,7 +244,7 @@ private void setState(AccessCertificationCampaignType campaign, AccessCertificat } private PropertyDelta createStageNumberDelta(int number) { - return PropertyDelta.createReplaceDelta(helper.getCampaignObjectDefinition(), AccessCertificationCampaignType.F_CURRENT_STAGE_NUMBER, number); + return PropertyDelta.createReplaceDelta(helper.getCampaignObjectDefinition(), AccessCertificationCampaignType.F_STAGE_NUMBER, number); } private PropertyDelta createStateDelta(AccessCertificationCampaignStateType state) { @@ -259,7 +260,7 @@ public void moveToNextStage(AccessCertificationCampaignType campaign, AccessCert Validate.notNull(campaign, "certificationCampaign"); Validate.notNull(campaign.getOid(), "certificationCampaign.oid"); - int stageNumber = campaign.getCurrentStageNumber(); + int stageNumber = campaign.getStageNumber(); if (LOGGER.isTraceEnabled()) { LOGGER.trace("moveToNextStage starting; campaign = {}, stage number = {}", @@ -364,16 +365,18 @@ public boolean handle(PrismObject object, OperationResult parentResu AccessCertificationCaseType _case = caseList.get(i); _case.setReviewRequestedTimestamp(stage.getStart()); _case.setReviewDeadline(stage.getEnd()); - _case.setEnabled(true); _case.setCurrentResponse(null); - _case.setCurrentResponseStage(1); + _case.setCurrentStageNumber(1); + + reviewersHelper.setupReviewersForCase(_case, campaign, reviewerSpec, task, result); + + List decisions = createEmptyDecisionsForCase(_case.getReviewerRef(), 1); + _case.getDecision().addAll(decisions); PrismContainerValue caseCVal = _case.asPrismContainerValue(); caseCVal.setId((long) (i + 1)); caseDelta.addValueToAdd(caseCVal); - reviewersHelper.setupReviewersForCase(_case, campaign, reviewerSpec, task, result); - if (LOGGER.isTraceEnabled()) { LOGGER.trace("Adding certification case:\n{}", caseCVal.debugDump()); } @@ -394,11 +397,29 @@ public boolean handle(PrismObject object, OperationResult parentResu LOGGER.trace("Created stage and {} cases for campaign {}", caseList.size(), campaignShortName); } + // BRUTAL HACK: we fill-in decisions when in stage 1 (to be fixed in repository implementation) + private List createEmptyDecisionsForCase(List forReviewers, int forStage) { + long id = 1; + List decisions = new ArrayList<>(); + for (ObjectReferenceType reviewer : forReviewers) { + AccessCertificationDecisionType decision = new AccessCertificationDecisionType(prismContext); + decision.setReviewerRef(reviewer); + decision.setStageNumber(forStage); + decision.setResponse(null); + decision.setTimestamp(null); + if (forStage == 1) { + decision.setId(id++); + } + decisions.add(decision); + } + return decisions; + } + private void updateCases(AccessCertificationCampaignType campaign, AccessCertificationStageType stage, Task task, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException, SecurityViolationException, ConfigurationException, CommunicationException { LOGGER.trace("Updating reviewers and timestamps for cases in {}", ObjectTypeUtil.toShortString(campaign)); List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); - int stageToBe = campaign.getCurrentStageNumber() + 1; + int stageToBe = campaign.getStageNumber() + 1; AccessCertificationReviewerSpecificationType reviewerSpec = reviewersHelper.findReviewersSpecification(campaign, stageToBe, task, result); @@ -407,14 +428,14 @@ private void updateCases(AccessCertificationCampaignType campaign, AccessCertifi for (int i = 0; i < caseList.size(); i++) { AccessCertificationCaseType _case = caseList.get(i); - boolean enabled = computationHelper.computeEnabled(_case); - PropertyDelta enabledDelta = PropertyDelta.createModificationReplaceProperty( - new ItemPath( - new NameItemPathSegment(AccessCertificationCampaignType.F_CASE), - new IdItemPathSegment(_case.asPrismContainerValue().getId()), - new NameItemPathSegment(AccessCertificationCaseType.F_ENABLED)), - helper.getCampaignObjectDefinition(), enabled); - campaignDeltaList.add(enabledDelta); + boolean enabled = computationHelper.computeEnabled(campaign, _case); +// PropertyDelta enabledDelta = PropertyDelta.createModificationReplaceProperty( +// new ItemPath( +// new NameItemPathSegment(AccessCertificationCampaignType.F_CASE), +// new IdItemPathSegment(_case.asPrismContainerValue().getId()), +// new NameItemPathSegment(AccessCertificationCaseType.F_ENABLED)), +// helper.getCampaignObjectDefinition(), enabled); +// campaignDeltaList.add(enabledDelta); if (enabled) { reviewersHelper.setupReviewersForCase(_case, campaign, reviewerSpec, task, result); @@ -430,6 +451,13 @@ private void updateCases(AccessCertificationCampaignType campaign, AccessCertifi helper.getCampaignObjectDefinition(), CloneUtil.cloneCollectionMembers(reviewersRef.getValues())); campaignDeltaList.add(reviewerDelta); + List newDecisions = createEmptyDecisionsForCase(_case.getReviewerRef(), stageToBe); + PrismContainerDefinition decisionDef = + prismContext.getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AccessCertificationCaseType.class) + .findContainerDefinition(AccessCertificationCaseType.F_DECISION); + ContainerDelta decisionDelta = ContainerDelta.createDelta(AccessCertificationCaseType.F_DECISION, decisionDef); + decisionDelta.addValuesToAdd(newDecisions); + PropertyDelta reviewRequestedTimestampDelta = PropertyDelta.createModificationReplaceProperty( new ItemPath( new NameItemPathSegment(AccessCertificationCampaignType.F_CASE), @@ -461,7 +489,7 @@ private void updateCases(AccessCertificationCampaignType campaign, AccessCertifi new ItemPath( new NameItemPathSegment(AccessCertificationCampaignType.F_CASE), new IdItemPathSegment(_case.asPrismContainerValue().getId()), - new NameItemPathSegment(AccessCertificationCaseType.F_CURRENT_RESPONSE_STAGE)), + new NameItemPathSegment(AccessCertificationCaseType.F_CURRENT_STAGE_NUMBER)), helper.getCampaignObjectDefinition(), stageToBe); campaignDeltaList.add(currentResponseStageDelta); @@ -526,11 +554,11 @@ void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCerti // notifications campaign = refreshCampaign(campaign, task, result); - if (campaign.getCurrentStageNumber() == 1) { + if (campaign.getStageNumber() == 1) { eventHelper.onCampaignStart(campaign, task, result); } eventHelper.onCampaignStageStart(campaign, task, result); - Collection reviewers = eventHelper.getCurrentReviewers(caseList); + Collection reviewers = eventHelper.getCurrentReviewers(campaign, caseList); for (String reviewerOid : reviewers) { List cases = queryHelper.getCasesForReviewer(campaign, reviewerOid, task, result); ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); @@ -562,7 +590,7 @@ private List createCurrentResponsesDeltas(AccessCertificationCampaign for (int i = 0; i < caseList.size(); i++) { AccessCertificationCaseType _case = caseList.get(i); - if (Boolean.FALSE.equals(_case.isEnabled())) { + if (_case.getCurrentStageNumber() != campaign.getStageNumber()) { continue; } AccessCertificationResponseType newResponse = computationHelper.computeResponseForStage(_case, campaign); diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java index 6bf872fd156..3af453f23ae 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageApproachingTriggerHandler.java @@ -83,9 +83,9 @@ public void handle(PrismObject prismObject, Task task, eventHelper.onCampaignStageDeadlineApproaching(campaign, task, result); List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); - Collection reviewers = eventHelper.getCurrentReviewers(caseList); + Collection reviewers = eventHelper.getCurrentReviewers(campaign, caseList); for (String reviewerOid : reviewers) { - List reviewerCaseList = queryHelper.selectCasesForReviewer(caseList, reviewerOid); + List reviewerCaseList = queryHelper.selectCasesForReviewer(campaign, caseList, reviewerOid); ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); eventHelper.onReviewDeadlineApproaching(reviewerRef, reviewerCaseList, campaign, task, result); } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageTriggerHandler.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageTriggerHandler.java index 890458a89b5..fa4dbdf7d95 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageTriggerHandler.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCloseStageTriggerHandler.java @@ -76,7 +76,7 @@ public void handle(PrismObject prismObject, Task task, AccessCertificationCampaignType campaign = (AccessCertificationCampaignType) object; LOGGER.info("Automatically closing current stage of {}", ObjectTypeUtil.toShortString(campaign)); - int currentStageNumber = campaign.getCurrentStageNumber(); + int currentStageNumber = campaign.getStageNumber(); certificationManager.closeCurrentStage(campaign.getOid(), currentStageNumber, task, result); if (currentStageNumber < CertCampaignTypeUtil.getNumberOfStages(campaign)) { LOGGER.info("Automatically opening next stage of {}", ObjectTypeUtil.toShortString(campaign)); diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java index 4b693f93869..04a27132efd 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java @@ -175,7 +175,7 @@ public void openNextStage(String campaignOid, int requestedStageNumber, Task tas LOGGER.debug("openNextStage starting for {}", ObjectTypeUtil.toShortString(campaign)); } - final int currentStageNumber = campaign.getCurrentStageNumber(); + final int currentStageNumber = campaign.getStageNumber(); final int stages = CertCampaignTypeUtil.getNumberOfStages(campaign); final AccessCertificationCampaignStateType state = campaign.getState(); LOGGER.trace("openNextStage: currentStageNumber={}, stages={}, requestedStageNumber={}, state={}", currentStageNumber, stages, requestedStageNumber, state); @@ -225,7 +225,7 @@ public void closeCurrentStage(String campaignOid, int stageNumberToClose, Task t LOGGER.debug("closeCurrentStage starting for {}", ObjectTypeUtil.toShortString(campaign)); } - final int currentStageNumber = campaign.getCurrentStageNumber(); + final int currentStageNumber = campaign.getStageNumber(); final int stages = CertCampaignTypeUtil.getNumberOfStages(campaign); final AccessCertificationCampaignStateType state = campaign.getState(); LOGGER.trace("closeCurrentStage: currentStageNumber={}, stages={}, stageNumberToClose={}, state={}", currentStageNumber, stages, stageNumberToClose, state); @@ -262,7 +262,7 @@ public void startRemediation(String campaignOid, Task task, OperationResult pare LOGGER.debug("startRemediation starting for {}", ObjectTypeUtil.toShortString(campaign)); } - final int currentStageNumber = campaign.getCurrentStageNumber(); + final int currentStageNumber = campaign.getStageNumber(); final int lastStageNumber = CertCampaignTypeUtil.getNumberOfStages(campaign); final AccessCertificationCampaignStateType state = campaign.getState(); LOGGER.trace("startRemediation: currentStageNumber={}, stages={}, state={}", currentStageNumber, lastStageNumber, state); @@ -383,14 +383,14 @@ public AccessCertificationCasesStatisticsType getCampaignStatistics(String campa AccessCertificationCasesStatisticsType stat = new AccessCertificationCasesStatisticsType(prismContext); AccessCertificationCampaignType campaign = helper.getCampaign(campaignOid, null, task, result); - int currentStageNumber = campaign.getCurrentStageNumber(); + int currentStageNumber = campaign.getStageNumber(); AccessCertificationCampaignStateType state = campaign.getState(); List campaignCases = queryHelper.searchCases(campaign.getOid(), null, null, task, result); int accept=0, revoke=0, revokeRemedied=0, reduce=0, reduceRemedied=0, delegate=0, noDecision=0, noResponse=0; for (AccessCertificationCaseType _case : campaignCases) { - if (currentStageOnly && !_case.isEnabled()) { + if (currentStageOnly && _case.getCurrentStageNumber() != campaign.getStageNumber()) { continue; } AccessCertificationResponseType response = _case.getCurrentResponse(); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java index 1507c15318c..8e81e3b6326 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java @@ -256,7 +256,7 @@ protected void assertApproximateTime(String itemName, Date expected, XMLGregoria protected void assertStateAndStage(AccessCertificationCampaignType campaign, AccessCertificationCampaignStateType state, int stage) { assertEquals("Unexpected campaign state", state, campaign.getState()); - assertEquals("Unexpected stage number", stage, campaign.getCurrentStageNumber()); + assertEquals("Unexpected stage number", stage, campaign.getStageNumber()); } protected void assertDefinitionAndOwner(AccessCertificationCampaignType campaign, AccessCertificationDefinitionType certificationDefinition) { @@ -269,8 +269,8 @@ protected void assertDefinitionAndOwner(AccessCertificationCampaignType campaign protected void assertCaseReviewers(AccessCertificationCaseType _case, AccessCertificationResponseType currentResponse, boolean enabled, int currentResponseStage, List reviewerOidList) { assertEquals("wrong current response", currentResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", enabled, _case.isEnabled()); - assertEquals("wrong current response stage number", (Integer) currentResponseStage, _case.getCurrentResponseStage()); + //assertEquals("wrong enabled", enabled, _case.isEnabled()); + assertEquals("wrong current response stage number", currentResponseStage, _case.getCurrentStageNumber()); Set realReviewerOids = new HashSet<>(); for (ObjectReferenceType ref : _case.getReviewerRef()) { realReviewerOids.add(ref.getOid()); @@ -302,19 +302,19 @@ protected void assertDecision(AccessCertificationCaseType _case, AccessCertifica assertEquals("wrong stage number", stageNumber, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", enabled, _case.isEnabled()); + //assertEquals("wrong enabled", enabled, _case.isEnabled()); } protected void assertNoDecision(AccessCertificationCaseType _case, AccessCertificationResponseType aggregatedResponse, boolean enabled) { assertEquals("wrong # of decisions", 0, _case.getDecision().size()); assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", enabled, _case.isEnabled()); + //assertEquals("wrong enabled", enabled, _case.isEnabled()); } protected void assertCurrentState(AccessCertificationCaseType _case, AccessCertificationResponseType aggregatedResponse, int currentResponseStage, boolean enabled) { assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong current response stage number", (Integer) currentResponseStage, _case.getCurrentResponseStage()); - assertEquals("wrong enabled", enabled, _case.isEnabled()); + assertEquals("wrong current response stage number", currentResponseStage, _case.getCurrentStageNumber()); +// assertEquals("wrong enabled", enabled, _case.isEnabled()); } protected void assertDecisions(AccessCertificationCaseType _case, int count) { @@ -329,7 +329,7 @@ protected void assertDecision2(AccessCertificationCaseType _case, AccessCertific assertEquals("wrong comment", comment, decision.getComment()); assertApproximateTime("timestamp", new Date(), decision.getTimestamp()); assertEquals("wrong current response", aggregatedResponse, _case.getCurrentResponse()); - assertEquals("wrong enabled", enabled, _case.isEnabled()); +// assertEquals("wrong enabled", enabled, _case.isEnabled()); } } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java index d1783dd7b98..2f2089b1019 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java @@ -59,7 +59,6 @@ import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; -import static org.testng.AssertJUnit.fail; /** * Very simple certification test. @@ -115,7 +114,7 @@ public void test010CreateCampaign() throws Exception { protected void assertStateAndStage(AccessCertificationCampaignType campaign, AccessCertificationCampaignStateType state, int stage) { assertEquals("Unexpected campaign state", state, campaign.getState()); - assertEquals("Unexpected stage number", stage, campaign.getCurrentStageNumber()); + assertEquals("Unexpected stage number", stage, campaign.getStageNumber()); } @Test @@ -307,7 +306,7 @@ public void test100RecordDecision() throws Exception { assertEquals("wrong stage number", 1, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", AccessCertificationResponseType.ACCEPT, superuserCase.getCurrentResponse()); - assertEquals("wrong enabled", true, superuserCase.isEnabled()); + //assertEquals("wrong enabled", true, superuserCase.isEnabled()); } @Test @@ -351,7 +350,7 @@ public void test105RecordAcceptJackCeo() throws Exception { assertEquals("wrong stage number", 1, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", AccessCertificationResponseType.ACCEPT, ceoCase.getCurrentResponse()); - assertEquals("wrong enabled", true, ceoCase.isEnabled()); + //assertEquals("wrong enabled", true, ceoCase.isEnabled()); } @Test @@ -396,7 +395,7 @@ public void test110RecordRevokeJackCeo() throws Exception { assertEquals("wrong stage number", 1, storedDecision.getStageNumber()); assertApproximateTime("timestamp", new Date(), storedDecision.getTimestamp()); assertEquals("wrong current response", AccessCertificationResponseType.REVOKE, ceoCase.getCurrentResponse()); - assertEquals("wrong enabled", true, ceoCase.isEnabled()); + //assertEquals("wrong enabled", true, ceoCase.isEnabled()); } protected void checkAllCases(Collection caseList) { @@ -471,7 +470,7 @@ public void test200StartRemediation() throws Exception { campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); assertEquals("wrong campaign state", CLOSED, campaign.getState()); - assertEquals("wrong campaign stage", 2, campaign.getCurrentStageNumber()); + assertEquals("wrong campaign stage", 2, campaign.getStageNumber()); assertDefinitionAndOwner(campaign, certificationDefinition); // TODO assertApproximateTime("end time", new Date(), campaign.getEnd()); assertEquals("wrong # of stages", 1, campaign.getStage().size()); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java index 3bb23c1b55e..85aef595dbb 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java @@ -453,7 +453,7 @@ public void test300StartRemediation() throws Exception { campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); assertEquals("wrong campaign state", CLOSED, campaign.getState()); - assertEquals("wrong campaign stage", 3, campaign.getCurrentStageNumber()); + assertEquals("wrong campaign stage", 3, campaign.getStageNumber()); assertDefinitionAndOwner(campaign, certificationDefinition); // TODO assertApproximateTime("end time", new Date(), campaign.getEnd()); assertEquals("wrong # of stages", 2, campaign.getStage().size()); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java index 80634fc333a..509c4d8f7ff 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java @@ -119,7 +119,7 @@ public void test010CreateCampaign() throws Exception { protected void assertStateAndStage(AccessCertificationCampaignType campaign, AccessCertificationCampaignStateType state, int stage) { assertEquals("Unexpected campaign state", state, campaign.getState()); - assertEquals("Unexpected stage number", stage, campaign.getCurrentStageNumber()); + assertEquals("Unexpected stage number", stage, campaign.getStageNumber()); } @Test @@ -791,7 +791,7 @@ public void test300StartRemediation() throws Exception { campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); assertEquals("wrong campaign state", CLOSED, campaign.getState()); - assertEquals("wrong campaign stage", 3, campaign.getCurrentStageNumber()); + assertEquals("wrong campaign stage", 3, campaign.getStageNumber()); assertDefinitionAndOwner(campaign, certificationDefinition); // TODO assertApproximateTime("end time", new Date(), campaign.getEnd()); assertEquals("wrong # of stages", 2, campaign.getStage().size()); diff --git a/model/certification-impl/src/test/resources/logback-test.xml b/model/certification-impl/src/test/resources/logback-test.xml index 4ed61eed5f6..e8444e1057a 100644 --- a/model/certification-impl/src/test/resources/logback-test.xml +++ b/model/certification-impl/src/test/resources/logback-test.xml @@ -35,6 +35,7 @@ + diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/AccessCertificationEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/AccessCertificationEvent.java index 700e33308fd..c0b6c440f60 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/AccessCertificationEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/AccessCertificationEvent.java @@ -92,6 +92,6 @@ public AccessCertificationStageDefinitionType getCurrentStageDefinition() { if (campaign.getState() != IN_REVIEW_STAGE && campaign.getState() != REVIEW_STAGE_DONE) { return null; } - return CertCampaignTypeUtil.findStageDefinition(campaign, campaign.getCurrentStageNumber()); + return CertCampaignTypeUtil.findStageDefinition(campaign, campaign.getStageNumber()); } } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java index cadbdec7ad7..c4c6a8f2f41 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java @@ -57,7 +57,7 @@ public boolean isCategoryType(EventCategoryType eventCategoryType) { public Collection getCasesWithoutResponse() { List rv = new ArrayList<>(); for (AccessCertificationCaseType aCase : cases) { - if (!hasResponse(aCase, getRequesteeOid(), campaign.getCurrentStageNumber())) { + if (!hasResponse(aCase, getRequesteeOid(), campaign.getStageNumber())) { rv.add(aCase); } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java index 8c1ef72f77d..0e2fc2c5c4c 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/helpers/CertHelper.java @@ -78,7 +78,7 @@ public String formatState(AccessCertificationEvent event) { } private String formatStage(AccessCertificationCampaignType campaign) { - String rv = campaign.getCurrentStageNumber() + "/" + CertCampaignTypeUtil.getNumberOfStages(campaign); + String rv = campaign.getStageNumber() + "/" + CertCampaignTypeUtil.getNumberOfStages(campaign); AccessCertificationStageType stage = CertCampaignTypeUtil.findCurrentStage(campaign); if (StringUtils.isNotEmpty(stage.getName())) { @@ -91,7 +91,7 @@ public String getStageShortName(AccessCertificationCampaignType campaign) { if (campaign.getState() == AccessCertificationCampaignStateType.IN_REMEDIATION) { return "remediation stage"; } else { - return "stage " + campaign.getCurrentStageNumber() + "/" + CertCampaignTypeUtil.getNumberOfStages(campaign); + return "stage " + campaign.getStageNumber() + "/" + CertCampaignTypeUtil.getNumberOfStages(campaign); } } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/OrgStructTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/OrgStructTest.java index 82106edb082..b172bfbf620 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/OrgStructTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/OrgStructTest.java @@ -603,8 +603,7 @@ public void test011OrgFilter() throws Exception { ObjectQuery query = new ObjectQuery(); PrismReferenceValue baseOrgRef = new PrismReferenceValue(ORG_F001_OID); ObjectFilter filter = OrgFilter.createOrg(baseOrgRef, OrgFilter.Scope.ONE_LEVEL); - ObjectPaging paging = ObjectPaging.createEmptyPaging(); - paging.setOrderBy(ObjectType.F_NAME); + ObjectPaging paging = ObjectPaging.createPaging(null, null, ObjectType.F_NAME, null); query.setFilter(filter); query.setPaging(paging); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 68902f68442..d293d17649b 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.match.PolyStringNormMatchingRule; import com.evolveum.midpoint.prism.match.PolyStringOrigMatchingRule; import com.evolveum.midpoint.prism.path.ItemPath; @@ -64,9 +65,9 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; @@ -88,8 +89,6 @@ import com.evolveum.prism.xml.ns._public.query_3.QueryType; import org.apache.commons.lang.StringUtils; import org.hibernate.Session; -import org.hibernate.criterion.ProjectionList; -import org.hibernate.criterion.Projections; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; @@ -106,7 +105,20 @@ import java.util.Date; import java.util.List; +import static com.evolveum.midpoint.prism.PrismConstants.T_ID; +import static com.evolveum.midpoint.prism.PrismConstants.T_PARENT; import static com.evolveum.midpoint.prism.query.OrderDirection.*; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REVIEW_STAGE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_STATE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CURRENT_STAGE_NUMBER; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_DECISION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_REVIEWER_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_REVIEW_DEADLINE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_REVIEW_REQUESTED_TIMESTAMP; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_STAGE_NUMBER; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_NAME; /** * @author lazyman @@ -153,7 +165,7 @@ public void test001QueryNameNorm() throws Exception { * ### user: Equal (name, "asdf", PolyStringNorm) */ ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) - .item(UserType.F_NAME).eqPoly("asdf", "asdf").matchingNorm().build(); + .item(F_NAME).eqPoly("asdf", "asdf").matchingNorm().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -177,12 +189,12 @@ public void test002QueryNameOrig() throws Exception { /* * ### user: Equal (name, "asdf", PolyStringOrig) */ - ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + ObjectFilter filter = EqualFilter.createEqual(F_NAME, UserType.class, prismContext, PolyStringOrigMatchingRule.NAME, new PolyString("asdf", "asdf")); ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) - .item(UserType.F_NAME).eqPoly("asdf", "asdf").matchingOrig().build(); + .item(F_NAME).eqPoly("asdf", "asdf").matchingOrig().build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -206,12 +218,12 @@ public void test003QueryNameStrict() throws Exception { /* * ### user: Equal (name, "asdf", PolyStringOrig) */ - ObjectFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + ObjectFilter filter = EqualFilter.createEqual(F_NAME, UserType.class, prismContext, null, new PolyString("asdf", "asdf")); ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) - .item(UserType.F_NAME).eqPoly("asdf", "asdf").build(); + .item(F_NAME).eqPoly("asdf", "asdf").build(); String expected = "select\n" + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + @@ -666,15 +678,15 @@ public void test080QueryExistsAssignment() throws Exception { ExistsFilter filter = ExistsFilter.createExists(new ItemPath(UserType.F_ASSIGNMENT), UserType.class, prismContext, EqualFilter.createEqual(new ItemPath(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), AssignmentType.class, prismContext, null, ActivationStatusType.ENABLED)); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); - query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); + query0.setPaging(ObjectPaging.createPaging(F_NAME, ASCENDING)); -// ObjectQuery query1 = QueryBuilder.queryFor(UserType.class, prismContext) -// .exists(UserType.F_ASSIGNMENT) -// .item(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS) -// .eq(ActivationStatusType.ENABLED) -// .asc(UserType.F_NAME) -// .build(); + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .exists(UserType.F_ASSIGNMENT) + .item(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS) + .eq(ActivationStatusType.ENABLED) + .asc(F_NAME) + .build(); String real = getInterpretedQuery2(session, UserType.class, query); String expected = "select\n" + @@ -709,10 +721,10 @@ public void test100QueryObjectByName() throws Exception { * ==> from RObject o where name.orig = 'cpt. Jack Sparrow' and name.norm = 'cpt jack sparrow' * order by name.orig asc */ - EqualFilter filter = EqualFilter.createEqual(ObjectType.F_NAME, ObjectType.class, prismContext, + EqualFilter filter = EqualFilter.createEqual(F_NAME, ObjectType.class, prismContext, null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + query.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); String real = getInterpretedQuery2(session, ObjectType.class, query); String expected = "select\n" + @@ -1187,13 +1199,15 @@ public void test300CountObjectOrderByName() throws Exception { Session session = open(); try { - EqualFilter filter = EqualFilter.createEqual(UserType.F_NAME, UserType.class, prismContext, + EqualFilter filter = EqualFilter.createEqual(F_NAME, UserType.class, prismContext, null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); - ObjectQuery query = ObjectQuery.createObjectQuery(filter, - ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + ObjectQuery query0 = ObjectQuery.createObjectQuery(filter, + ObjectPaging.createPaging(F_NAME, ASCENDING)); -// ObjectQuery query1 = QueryBuilder.queryFor(UserType.class, prismContext).asc(ObjectType.F_NAME).build(); + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(F_NAME).eqPoly("cpt. Jack Sparrow", "cpt jack sparrow") + .asc(F_NAME).build(); String real = getInterpretedQuery2(session, UserType.class, query, true); String expected = "select\n" + @@ -1216,7 +1230,7 @@ public void test310CountObjectOrderByNameWithoutFilter() throws Exception { Session session = open(); try { - ObjectPaging paging = ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING); + ObjectPaging paging = ObjectPaging.createPaging(null, null, F_NAME, ASCENDING); ObjectQuery query = ObjectQuery.createObjectQuery(null, paging); String real = getInterpretedQuery2(session, ObjectType.class, query, true); @@ -1243,7 +1257,7 @@ public void test320CountTaskOrderByName() throws Exception { EqualFilter filter = EqualFilter.createEqual(TaskType.F_PARENT, TaskType.class, prismContext, null); ObjectQuery query = ObjectQuery.createObjectQuery(filter); - query.setPaging(ObjectPaging.createPaging(null, null, TaskType.F_NAME, ASCENDING)); + query.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); String real = getInterpretedQuery2(session, TaskType.class, query, true); String expected = "select\n" + @@ -1296,7 +1310,7 @@ public void test340QueryOrgTreeFindOrgs() throws Exception { OrgFilter orgFilter = OrgFilter.createOrg("some oid", OrgFilter.Scope.ONE_LEVEL); ObjectQuery objectQuery = ObjectQuery.createObjectQuery(orgFilter); - objectQuery.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + objectQuery.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); objectQuery.setUseNewQueryInterpreter(true); // ObjectQuery query1 = QueryBuilder.queryFor(OrgType.class, prismContext) @@ -1723,7 +1737,7 @@ private void checkQueryResult(Class type, String oid, OrgFilter orgFilter = OrgFilter.createOrg(oid, scope); ObjectQuery query = ObjectQuery.createObjectQuery(orgFilter); - query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + query.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); query.setUseNewQueryInterpreter(true); OperationResult result = new OperationResult("checkQueryResult"); @@ -1749,13 +1763,13 @@ public void test510QueryNameAndOrg() throws Exception { Session session = open(); try { - EqualFilter eqFilter = EqualFilter.createEqual(ObjectType.F_NAME, ObjectType.class, prismContext, + EqualFilter eqFilter = EqualFilter.createEqual(F_NAME, ObjectType.class, prismContext, null, new PolyString("cpt. Jack Sparrow", "cpt jack sparrow")); OrgFilter orgFilter = OrgFilter.createOrg("12341234-1234-1234-1234-123412341234"); ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(eqFilter, orgFilter)); - query.setPaging(ObjectPaging.createPaging(null, null, ObjectType.F_NAME, ASCENDING)); + query.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); String real = getInterpretedQuery2(session, UserType.class, query); @@ -1820,7 +1834,7 @@ public void test530queryUserSubstringName() throws Exception { Session session = open(); try { - SubstringFilter substring = SubstringFilter.createSubstring(ObjectType.F_NAME, ObjectType.class, + SubstringFilter substring = SubstringFilter.createSubstring(F_NAME, ObjectType.class, prismContext, PolyStringOrigMatchingRule.NAME, "a"); substring.setAnchorStart(true); ObjectQuery objectQuery = ObjectQuery.createObjectQuery(substring); @@ -1845,7 +1859,7 @@ public void test530queryUserSubstringName() throws Exception { int count = repositoryService.countObjects(ObjectType.class, objectQuery, result); AssertJUnit.assertEquals(2, count); - substring = SubstringFilter.createSubstring(ObjectType.F_NAME, ObjectType.class, + substring = SubstringFilter.createSubstring(F_NAME, ObjectType.class, prismContext, PolyStringOrigMatchingRule.NAME, "a"); objectQuery = ObjectQuery.createObjectQuery(substring); objectQuery.setUseNewQueryInterpreter(true); @@ -2450,7 +2464,7 @@ public void test730QueryCertCaseReviewer() throws Exception { try { PrismContainerDefinition caseDef = prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(AccessCertificationCaseType.class); - ObjectFilter filter = RefFilter.createReferenceEqual(new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), caseDef, "1234567890"); + ObjectFilter filter = RefFilter.createReferenceEqual(new ItemPath(F_REVIEWER_REF), caseDef, "1234567890"); ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); String expected = "select\n" + @@ -2474,21 +2488,20 @@ public void test730QueryCertCaseReviewer() throws Exception { public void test735QueryCertCaseReviewerAndEnabled() throws Exception { Session session = open(); try { - ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER); - ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( - new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), - AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); - ObjectFilter enabledFilter = EqualFilter.createEqual( - AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); - ObjectFilter filter = AndFilter.createAnd(reviewerFilter, enabledFilter); + PrismReferenceValue reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER).asReferenceValue(); + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .item(F_REVIEWER_REF).ref(reviewerRef) + .and().item(F_CURRENT_STAGE_NUMBER).eq().item(T_PARENT, AccessCertificationCampaignType.F_STAGE_NUMBER) + .build(); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); - String expected = "select\n" + + String expected = + "select\n" + " a.fullObject\n" + "from\n" + " RAccessCertificationCase a\n" + " left join a.reviewerRef r\n" + + " left join a.owner o\n" + "where\n" + " (\n" + " (\n" + @@ -2496,7 +2509,13 @@ public void test735QueryCertCaseReviewerAndEnabled() throws Exception { " r.relation = :relation and\n" + " r.type = :type\n" + " ) and\n" + - " a.enabled = :enabled\n" + + " (\n" + + " a.currentStageNumber = o.stageNumber or\n" + + " (\n" + + " a.currentStageNumber is null and\n" + + " o.stageNumber is null\n" + + " )\n" + + " )\n" + " )\n"; assertEqualsIgnoreWhitespace(expected, real); } finally { @@ -2505,34 +2524,41 @@ public void test735QueryCertCaseReviewerAndEnabled() throws Exception { } @Test - public void test745QueryCertCaseReviewerAndEnabledByDeadlineAsc() throws Exception { + public void test745QueryCertCaseReviewerAndEnabledByDeadlineAndOidAsc() throws Exception { Session session = open(); try { - ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER); - ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( - new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), - AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); - ObjectFilter enabledFilter = EqualFilter.createEqual( - AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); - ObjectFilter filter = AndFilter.createAnd(reviewerFilter, enabledFilter); - ObjectPaging paging = ObjectPaging.createPaging(new ItemPath(AccessCertificationCaseType.F_REVIEW_DEADLINE), ASCENDING); - ObjectQuery query = ObjectQuery.createObjectQuery(filter, paging); + PrismReferenceValue reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER).asReferenceValue(); + + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .item(F_REVIEWER_REF).ref(reviewerRef) + .and().item(F_CURRENT_STAGE_NUMBER).eq().item(T_PARENT, AccessCertificationCampaignType.F_STAGE_NUMBER) + .asc(F_REVIEW_DEADLINE).asc(T_ID) + .build(); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); - String expected = "select\n" + - " a.fullObject\n" + - "from\n" + - " RAccessCertificationCase a\n" + - " left join a.reviewerRef r\n" + - "where\n" + - " (\n" + - " (\n" + - " r.targetOid = :targetOid and\n" + - " r.relation = :relation and\n" + - " r.type = :type\n" + - " ) and\n" + - " a.enabled = :enabled\n" + - " )\n" + - "order by a.reviewDeadline asc\n"; + String expected = + "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.reviewerRef r\n" + + " left join a.owner o\n" + + "where\n" + + " (\n" + + " (\n" + + " r.targetOid = :targetOid and\n" + + " r.relation = :relation and\n" + + " r.type = :type\n" + + " ) and\n" + + " (\n" + + " a.currentStageNumber = o.stageNumber or\n" + + " (\n" + + " a.currentStageNumber is null and\n" + + " o.stageNumber is null\n" + + " )\n" + + " )\n" + + " )\n" + + "order by a.reviewDeadline asc, a.id asc\n"; assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -2543,21 +2569,30 @@ public void test745QueryCertCaseReviewerAndEnabledByDeadlineAsc() throws Excepti public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Exception { Session session = open(); try { - ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER); - ObjectFilter reviewerFilter = RefFilter.createReferenceEqual( - new ItemPath(AccessCertificationCaseType.F_REVIEWER_REF), - AccessCertificationCaseType.class, prismContext, reviewerRef.asReferenceValue()); - ObjectFilter enabledFilter = EqualFilter.createEqual( - AccessCertificationCaseType.F_ENABLED, AccessCertificationCaseType.class, prismContext, Boolean.TRUE); - ObjectFilter filter = AndFilter.createAnd(reviewerFilter, enabledFilter); - ObjectPaging paging = ObjectPaging.createPaging(new ItemPath(AccessCertificationCaseType.F_REVIEW_REQUESTED_TIMESTAMP), DESCENDING); - ObjectQuery query = ObjectQuery.createObjectQuery(filter, paging); + PrismReferenceValue reviewerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER).asReferenceValue(); + ItemPath statePath = new ItemPath(T_PARENT, F_STATE); + PrismPropertyDefinition stateDef = + prismContext.getSchemaRegistry() + .findComplexTypeDefinitionByCompileTimeClass(AccessCertificationCampaignType.class) + .findPropertyDefinition(F_STATE); + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .item(F_REVIEWER_REF).ref(reviewerRef) + .and().item(F_CURRENT_STAGE_NUMBER).eq().item(T_PARENT, AccessCertificationCampaignType.F_STAGE_NUMBER) + .and().item(statePath, stateDef).eq(IN_REVIEW_STAGE) + .desc(F_REVIEW_REQUESTED_TIMESTAMP) + .build(); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + + // TODO TODO TODO + // when referencing singleton more times (like a.owner here) we should do only 1 join + String expected = "select\n" + " a.fullObject\n" + "from\n" + " RAccessCertificationCase a\n" + " left join a.reviewerRef r\n" + + " left join a.owner o\n" + + " left join a.owner o2\n" + "where\n" + " (\n" + " (\n" + @@ -2565,7 +2600,14 @@ public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Excep " r.relation = :relation and\n" + " r.type = :type\n" + " ) and\n" + - " a.enabled = :enabled\n" + + " (\n" + + " a.currentStageNumber = o.stageNumber or\n" + + " (\n" + + " a.currentStageNumber is null and\n" + + " o.stageNumber is null\n" + + " )\n" + + " ) and\n" + + " o2.state = :state\n" + " )\n" + "order by a.reviewRequestedTimestamp desc"; assertEqualsIgnoreWhitespace(expected, real); @@ -2584,7 +2626,7 @@ public void test750DereferenceLink() throws Exception { */ ObjectFilter filter = SubstringFilter.createSubstring( - new ItemPath(UserType.F_LINK_REF, PrismConstants.T_OBJECT_REFERENCE, ShadowType.F_NAME), + new ItemPath(UserType.F_LINK_REF, PrismConstants.T_OBJECT_REFERENCE, F_NAME), UserType.class, prismContext, "test.com"); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -2624,7 +2666,7 @@ public void test752DereferenceLinkedResourceName() throws Exception { ObjectFilter filter = SubstringFilter.createSubstring( new ItemPath(UserType.F_LINK_REF, PrismConstants.T_OBJECT_REFERENCE, ShadowType.F_RESOURCE_REF, PrismConstants.T_OBJECT_REFERENCE, - ShadowType.F_NAME), + F_NAME), UserType.class, prismContext, PolyStringNormMatchingRule.NAME, "CSV"); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -2686,7 +2728,7 @@ public void test770CaseParentFilter() throws Exception { */ ObjectFilter filter = EqualFilter.createEqual( - new ItemPath(PrismConstants.T_PARENT, ObjectType.F_NAME), + new ItemPath(T_PARENT, F_NAME), AccessCertificationCaseType.class, prismContext, "Campaign 1"); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -2751,7 +2793,7 @@ public void test810OrderByParentCampaignName() throws Exception { */ ObjectQuery query = ObjectQuery.createObjectQuery( - new ObjectPaging(new ItemPath(PrismConstants.T_PARENT, ObjectType.F_NAME), DESCENDING)); + ObjectPaging.createPaging(new ItemPath(T_PARENT, F_NAME), DESCENDING)); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query); String expected = "select\n" + @@ -2777,9 +2819,9 @@ public void test820OrderByTargetName() throws Exception { */ ObjectQuery query = ObjectQuery.createObjectQuery( - new ObjectPaging(new ItemPath( + ObjectPaging.createPaging(new ItemPath( AccessCertificationCaseType.F_TARGET_REF, - PrismConstants.T_OBJECT_REFERENCE, ObjectType.F_NAME), ASCENDING)); + PrismConstants.T_OBJECT_REFERENCE, F_NAME), ASCENDING)); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query); String expected = "select\n" + @@ -2895,9 +2937,9 @@ public void test920DecisionsNotAnswered() throws Exception { /* * ### AccCertCase: Exists (decision: reviewerRef = XYZ and stage = ../stage and response is null or response = NO_RESPONSE) */ - ObjectQuery query = ObjectQuery.createObjectQuery( + ObjectQuery query0 = ObjectQuery.createObjectQuery( ExistsFilter.createExists( - new ItemPath(AccessCertificationCaseType.F_DECISION), + new ItemPath(F_DECISION), AccessCertificationCaseType.class, prismContext, AndFilter.createAnd( @@ -2907,11 +2949,11 @@ public void test920DecisionsNotAnswered() throws Exception { prismContext, "123456"), EqualFilter.createEqual( - new ItemPath(AccessCertificationDecisionType.F_STAGE_NUMBER), + new ItemPath(F_STAGE_NUMBER), AccessCertificationDecisionType.class, prismContext, null, - new ItemPath(PrismConstants.T_PARENT, AccessCertificationCaseType.F_CURRENT_RESPONSE_STAGE) + new ItemPath(T_PARENT, F_CURRENT_STAGE_NUMBER) ), OrFilter.createOr( EqualFilter.createEqual( @@ -2921,11 +2963,23 @@ public void test920DecisionsNotAnswered() throws Exception { EqualFilter.createEqual( AccessCertificationDecisionType.F_RESPONSE, AccessCertificationDecisionType.class, - prismContext, AccessCertificationResponseType.NO_RESPONSE) + prismContext, NO_RESPONSE) ) ) ) ); + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .exists(F_DECISION) + .block() + .item(AccessCertificationDecisionType.F_REVIEWER_REF).ref("123456") + .and().item(F_STAGE_NUMBER).eq().item(T_PARENT, F_CURRENT_STAGE_NUMBER) + .and().block() + .item(F_RESPONSE).isNull() + .or().item(F_RESPONSE).eq(NO_RESPONSE) + .endBlock() + .endBlock() + .build(); + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query); String expected = "select\n" + " a.fullObject\n" + @@ -2939,10 +2993,10 @@ public void test920DecisionsNotAnswered() throws Exception { " d.reviewerRef.relation = :relation\n" + " ) and\n" + " (\n" + - " d.stageNumber = a.currentResponseStage or\n" + + " d.stageNumber = a.currentStageNumber or\n" + " (\n" + " d.stageNumber is null and\n" + - " a.currentResponseStage is null\n" + + " a.currentStageNumber is null\n" + " )\n" + " ) and\n" + " (\n" + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 7da95e2328c..94c11a55309 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -20,10 +20,12 @@ import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; +import com.evolveum.midpoint.repo.sql.data.common.enums.RAccessCertificationCampaignState; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; @@ -31,11 +33,14 @@ import org.hibernate.annotations.Cascade; import org.hibernate.annotations.ForeignKey; +import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -53,24 +58,23 @@ public class RAccessCertificationCampaign extends RObject cases; + private REmbeddedReference ownerRef; + private String handlerUri; + private XMLGregorianCalendar start; + private XMLGregorianCalendar end; + private RAccessCertificationCampaignState state; + private Integer stageNumber; + @Embedded public RPolyString getName() { return name; } - public void setName(RPolyString name) { - this.name = name; - } - @Embedded public REmbeddedReference getDefinitionRef() { return definitionRef; } - public void setDefinitionRef(REmbeddedReference definitionRef) { - this.definitionRef = definitionRef; - } - @OneToMany(mappedBy = RAccessCertificationCase.F_OWNER, orphanRemoval = true) @ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) @@ -81,33 +85,98 @@ public Set getCase() { return cases; } + @Embedded + public REmbeddedReference getOwnerRef() { + return ownerRef; + } + + public String getHandlerUri() { + return handlerUri; + } + + @Column(name = "startTimestamp") + public XMLGregorianCalendar getStart() { + return start; + } + + @Column(name = "endTimestamp") + public XMLGregorianCalendar getEnd() { + return end; + } + + public RAccessCertificationCampaignState getState() { + return state; + } + + public Integer getStageNumber() { + return stageNumber; + } + + public void setName(RPolyString name) { + this.name = name; + } + + public void setDefinitionRef(REmbeddedReference definitionRef) { + this.definitionRef = definitionRef; + } + public void setCase(Set cases) { this.cases = cases; } + public void setOwnerRef(REmbeddedReference ownerRef) { + this.ownerRef = ownerRef; + } + + public void setHandlerUri(String handlerUri) { + this.handlerUri = handlerUri; + } + + public void setStart(XMLGregorianCalendar start) { + this.start = start; + } + + public void setEnd(XMLGregorianCalendar end) { + this.end = end; + } + + public void setState(RAccessCertificationCampaignState state) { + this.state = state; + } + + public void setStageNumber(Integer stageNumber) { + this.stageNumber = stageNumber; + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof RAccessCertificationCampaign)) return false; if (!super.equals(o)) return false; - RAccessCertificationCampaign rACR = (RAccessCertificationCampaign) o; + RAccessCertificationCampaign that = (RAccessCertificationCampaign) o; - if (name != null ? !name.equals(rACR.name) : rACR.name != null) + if (name != null ? !name.equals(that.name) : that.name != null) return false; + if (definitionRef != null ? !definitionRef.equals(that.definitionRef) : that.definitionRef != null) return false; - if (definitionRef != null ? !definitionRef.equals(rACR.definitionRef) : rACR.definitionRef != null) - return false; - - // TODO what about cases? + if (ownerRef != null ? !ownerRef.equals(that.ownerRef) : that.ownerRef != null) return false; + if (handlerUri != null ? !handlerUri.equals(that.handlerUri) : that.handlerUri != null) return false; + if (start != null ? !start.equals(that.start) : that.start != null) return false; + if (end != null ? !end.equals(that.end) : that.end != null) return false; + if (state != that.state) return false; + return !(stageNumber != null ? !stageNumber.equals(that.stageNumber) : that.stageNumber != null); - return true; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (name != null ? name.hashCode() : 0); - // TODO definitionRef ? + result = 31 * result + (handlerUri != null ? handlerUri.hashCode() : 0); + result = 31 * result + (start != null ? start.hashCode() : 0); + result = 31 * result + (end != null ? end.hashCode() : 0); + result = 31 * result + (state != null ? state.hashCode() : 0); + result = 31 * result + (stageNumber != null ? stageNumber.hashCode() : 0); return result; } @@ -129,6 +198,12 @@ public static void copyFromJAXB(AccessCertificationCampaignType jaxb, RAccessCer } } + repo.setOwnerRef(RUtil.jaxbRefToEmbeddedRepoRef(jaxb.getOwnerRef(), prismContext)); + repo.setHandlerUri(jaxb.getHandlerUri()); + repo.setStart(jaxb.getStart()); + repo.setEnd(jaxb.getEnd()); + repo.setState(RUtil.getRepoEnumValue(jaxb.getState(), RAccessCertificationCampaignState.class)); + repo.setStageNumber(jaxb.getStageNumber()); } @Override diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 560f766d24a..9f8ecd02cb2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -37,6 +37,7 @@ import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; +import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; @@ -179,7 +180,7 @@ public abstract class RObject implements Metadata decisions; private RAccessCertificationResponse currentResponse; - private Integer currentResponseStage; + private Integer currentStageNumber; public RAccessCertificationCase() { this(null); @@ -128,7 +128,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") - @NotQueryable + @IdQueryProperty public Integer getId() { return id; } @@ -158,12 +158,6 @@ public REmbeddedReference getObjectRef() { return objectRef; } - @Deprecated // probably will be replaced by query "case.currentResponseStage = campaign.currentStage" - @Column(name = "case_enabled") - public boolean isEnabled() { - return enabled; - } - public XMLGregorianCalendar getReviewRequestedTimestamp() { return reviewRequestedTimestamp; } @@ -190,8 +184,8 @@ public RAccessCertificationResponse getCurrentResponse() { return currentResponse; } - public Integer getCurrentResponseStage() { - return currentResponseStage; + public Integer getCurrentStageNumber() { + return currentStageNumber; } public void setOwner(RObject owner) { @@ -214,10 +208,6 @@ public void setObjectRef(REmbeddedReference objectRef) { this.objectRef = objectRef; } - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - public void setReviewRequestedTimestamp(XMLGregorianCalendar reviewRequestedTimestamp) { this.reviewRequestedTimestamp = reviewRequestedTimestamp; } @@ -238,8 +228,8 @@ public void setCurrentResponse(RAccessCertificationResponse currentResponse) { this.currentResponse = currentResponse; } - public void setCurrentResponseStage(Integer currentResponseStage) { - this.currentResponseStage = currentResponseStage; + public void setCurrentStageNumber(Integer currentStageNumber) { + this.currentStageNumber = currentStageNumber; } @Lob @@ -258,7 +248,6 @@ public boolean equals(Object o) { RAccessCertificationCase that = (RAccessCertificationCase) o; - if (enabled != that.enabled) return false; if (!Arrays.equals(fullObject, that.fullObject)) return false; if (ownerOid != null ? !ownerOid.equals(that.ownerOid) : that.ownerOid != null) return false; if (id != null ? !id.equals(that.id) : that.id != null) return false; @@ -273,7 +262,7 @@ public boolean equals(Object o) { return false; if (decisions != null ? !decisions.equals(that.decisions) : that.decisions != null) return false; if (currentResponse != that.currentResponse) return false; - return !(currentResponseStage != null ? !currentResponseStage.equals(that.currentResponseStage) : that.currentResponseStage != null); + return !(currentStageNumber != null ? !currentStageNumber.equals(that.currentStageNumber) : that.currentStageNumber != null); } @@ -284,12 +273,11 @@ public int hashCode() { result = 31 * result + (reviewerRef != null ? reviewerRef.hashCode() : 0); result = 31 * result + (objectRef != null ? objectRef.hashCode() : 0); result = 31 * result + (targetRef != null ? targetRef.hashCode() : 0); - result = 31 * result + (enabled ? 1 : 0); result = 31 * result + (reviewRequestedTimestamp != null ? reviewRequestedTimestamp.hashCode() : 0); result = 31 * result + (reviewDeadline != null ? reviewDeadline.hashCode() : 0); result = 31 * result + (remediedTimestamp != null ? remediedTimestamp.hashCode() : 0); result = 31 * result + (currentResponse != null ? currentResponse.hashCode() : 0); - result = 31 * result + (currentResponseStage != null ? currentResponseStage.hashCode() : 0); + result = 31 * result + (currentStageNumber != null ? currentStageNumber.hashCode() : 0); return result; } @@ -329,18 +317,21 @@ public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificati private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, IdGeneratorResult generatorResult, PrismContext prismContext) { RAccessCertificationCase rCase = new RAccessCertificationCase(); - rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); + if (generatorResult == null) { + rCase.setTransient(true); + } else { + rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); + } rCase.setId(RUtil.toInteger(case1.getId())); rCase.setObjectRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getObjectRef(), prismContext)); rCase.setTargetRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getTargetRef(), prismContext)); rCase.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( case1.getReviewerRef(), prismContext, rCase, RCReferenceOwner.CASE_REVIEWER)); - rCase.setEnabled(case1.isEnabled()); rCase.setReviewRequestedTimestamp(case1.getReviewRequestedTimestamp()); rCase.setReviewDeadline(case1.getReviewDeadline()); rCase.setRemediedTimestamp(case1.getRemediedTimestamp()); rCase.setCurrentResponse(RUtil.getRepoEnumValue(case1.getCurrentResponse(), RAccessCertificationResponse.class)); - rCase.setCurrentResponseStage(case1.getCurrentResponseStage()); + rCase.setCurrentStageNumber(case1.getCurrentStageNumber()); for (AccessCertificationDecisionType decision : case1.getDecision()) { RAccessCertificationDecision rDecision = RAccessCertificationDecision.toRepo(rCase, decision, generatorResult, prismContext); rCase.getDecision().add(rDecision); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java index fffa66f76bb..1364f72d25d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java @@ -186,7 +186,11 @@ public static RAccessCertificationDecision toRepo(RAccessCertificationCase ownin private static RAccessCertificationDecision toRepo(AccessCertificationDecisionType decision, IdGeneratorResult generatorResult, PrismContext prismContext) { RAccessCertificationDecision rDecision = new RAccessCertificationDecision(); - rDecision.setTransient(generatorResult.isTransient(decision.asPrismContainerValue())); + if (generatorResult == null) { + rDecision.setTransient(true); + } else { + rDecision.setTransient(generatorResult.isTransient(decision.asPrismContainerValue())); + } rDecision.setId(RUtil.toInteger(decision.getId())); rDecision.setStageNumber(decision.getStageNumber()); rDecision.setReviewerRef(RUtil.jaxbRefToEmbeddedRepoRef(decision.getReviewerRef(), prismContext)); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java index f67755fa38b..4ec56fd8814 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java @@ -30,6 +30,7 @@ import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; +import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; @@ -149,7 +150,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") - @NotQueryable + @IdQueryProperty public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java index c57bb5d5eda..43a206009c3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.repo.sql.data.common.enums.RExclusionPolicy; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; @@ -90,6 +91,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") + @IdQueryProperty public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java index ce7eded878b..39eebb91943 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java @@ -4,6 +4,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; @@ -71,7 +72,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") - @NotQueryable + @IdQueryProperty public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationCampaignState.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationCampaignState.java new file mode 100644 index 00000000000..e4691b1f7fe --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/enums/RAccessCertificationCampaignState.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.data.common.enums; + +import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; + +/** + * @author mederly + */ +@JaxbType(type = AccessCertificationCampaignStateType.class) +public enum RAccessCertificationCampaignState implements SchemaEnum { + + CREATED(AccessCertificationCampaignStateType.CREATED), + IN_REVIEW_STAGE(AccessCertificationCampaignStateType.IN_REVIEW_STAGE), + REVIEW_STAGE_DONE(AccessCertificationCampaignStateType.REVIEW_STAGE_DONE), + IN_REMEDIATION(AccessCertificationCampaignStateType.IN_REMEDIATION), + CLOSED(AccessCertificationCampaignStateType.CLOSED); + + private AccessCertificationCampaignStateType status; + + private RAccessCertificationCampaignState(AccessCertificationCampaignStateType status) { + this.status = status; + } + + @Override + public AccessCertificationCampaignStateType getSchemaValue() { + return status; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java index 872dc0633ef..82fda89553c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java @@ -4,6 +4,7 @@ import com.evolveum.midpoint.repo.sql.data.common.container.Container; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; +import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; import com.evolveum.midpoint.repo.sql.util.RUtil; @@ -65,6 +66,7 @@ public String getOwnerOid() { @GeneratedValue(generator = "ContainerIdGenerator") @GenericGenerator(name = "ContainerIdGenerator", strategy = "com.evolveum.midpoint.repo.sql.util.ContainerIdGenerator") @Column(name = "id") + @IdQueryProperty public Integer getId() { return id; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index c7d3354fe75..8976b250f21 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -97,7 +97,7 @@ public void addCertificationCampaignCases(Session session, String campaignOid, C AccessCertificationCaseType caseType = new AccessCertificationCaseType(); caseType.setupContainerValue(value); caseType.setCampaignRef(ObjectTypeUtil.createObjectRef(campaignOid, ObjectTypes.ACCESS_CERTIFICATION_CAMPAIGN)); - RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, new IdGeneratorResult(), prismContext); + RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, null, prismContext); row.setId(currentId); currentId++; session.save(row); @@ -163,6 +163,8 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + deltaPath); } + // TODO treat missing decision IDs somehow + if (deltaPath.size() == 1) { if (delta.getValuesToDelete() != null) { // todo do 'bulk' delete like delete from ... where oid=? and id in (...) @@ -180,7 +182,7 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle } if (delta.getValuesToAdd() != null) { int currentId = generalHelper.findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; - affectedIds.add((long) currentId); + affectedIds.add((long) currentId); // TODO !!!!!!!!!!!!!!!!!! clear bug addCertificationCampaignCases(session, campaignOid, delta.getValuesToAdd(), currentId); } if (delta.getValuesToReplace() != null) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index e550f2a56fe..efaee739bce 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -28,6 +28,7 @@ import com.evolveum.midpoint.prism.query.NoneFilter; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectOrdering; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.OrFilter; @@ -115,7 +116,7 @@ public class QueryInterpreter2 { private static final Map AVAILABLE_MATCHERS; static { - Map matchers = new HashMap(); + Map matchers = new HashMap<>(); //default matcher with null key matchers.put(null, new DefaultMatcher()); matchers.put(PolyString.class, new PolyStringMatcher()); @@ -287,7 +288,7 @@ private void interpretPagingAndSorting(InterpretationContext context, ObjectQuer if (query.getPaging() instanceof ObjectPagingAfterOid) { updatePagingAndSortingByOid(hibernateQuery, (ObjectPagingAfterOid) query.getPaging()); // very special case - ascending ordering by OID (nothing more) } else { - updatePagingAndSorting(context, hibernateQuery, query.getPaging()); + updatePagingAndSorting(context, query.getPaging()); } } } @@ -297,17 +298,20 @@ protected void updatePagingAndSortingByOid(RootHibernateQuery hibernateQuery, Ob if (paging.getOrderBy() != null || paging.getDirection() != null || paging.getOffset() != null) { throw new IllegalArgumentException("orderBy, direction nor offset is allowed on ObjectPagingAfterOid"); } - hibernateQuery.setOrder(rootAlias + ".oid", OrderDirection.ASCENDING); + hibernateQuery.addOrdering(rootAlias + ".oid", OrderDirection.ASCENDING); if (paging.getMaxSize() != null) { hibernateQuery.setMaxResults(paging.getMaxSize()); } } - public void updatePagingAndSorting(InterpretationContext context, RootHibernateQuery hibernateQuery, + public void updatePagingAndSorting(InterpretationContext context, ObjectPaging paging) throws QueryException { + if (paging == null) { return; } + + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); if (paging.getOffset() != null) { hibernateQuery.setFirstResult(paging.getOffset()); } @@ -315,21 +319,26 @@ public void updatePagingAndSorting(InterpretationConte hibernateQuery.setMaxResults(paging.getMaxSize()); } - ItemPath orderByPath = paging.getOrderBy(); - if (ItemPath.isNullOrEmpty(orderByPath)) { - if (paging.getDirection() == null) { - return; - } else { - throw new QueryException("Ordering by empty property path is not possible"); - } + if (!paging.hasOrdering()) { + return; } + for (ObjectOrdering ordering : paging.getOrderingInstructions()) { + addOrdering(context, ordering); + } + } + + private void addOrdering(InterpretationContext context, ObjectOrdering ordering) throws QueryException { + + ItemPath orderByPath = ordering.getOrderBy(); + // TODO if we'd like to have order-by extension properties, we'd need to provide itemDefinition for them ProperDataSearchResult result = context.getItemPathResolver().findProperDataDefinition( context.getRootEntityDefinition(), orderByPath, null, JpaDataNodeDefinition.class); if (result == null) { - throw new QueryException("Unknown path '" + orderByPath + "', couldn't find definition for it, " + LOGGER.error("Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it."); + return; } JpaDataNodeDefinition targetDefinition = result.getLinkDefinition().getTargetDefinition(); if (targetDefinition instanceof JpaAnyContainerDefinition) { @@ -352,18 +361,21 @@ public void updatePagingAndSorting(InterpretationConte if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; } - if (paging.getDirection() != null) { - switch (paging.getDirection()) { + + RootHibernateQuery hibernateQuery = context.getHibernateQuery(); + if (ordering.getDirection() != null) { + switch (ordering.getDirection()) { case ASCENDING: - hibernateQuery.setOrder(hqlPropertyPath, OrderDirection.ASCENDING); + hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.ASCENDING); break; case DESCENDING: - hibernateQuery.setOrder(hqlPropertyPath, OrderDirection.DESCENDING); + hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.DESCENDING); break; } } else { - hibernateQuery.setOrder(hqlPropertyPath, OrderDirection.ASCENDING); + hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.ASCENDING); } + } public Matcher findMatcher(T value) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 769a6ca4c54..1b9306329bd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -16,6 +16,9 @@ package com.evolveum.midpoint.repo.sql.query2.definition; +import com.evolveum.midpoint.prism.path.IdentifierPathSegment; +import com.evolveum.midpoint.prism.path.ItemPathSegment; +import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.path.ParentPathSegment; import com.evolveum.midpoint.repo.sql.data.Marker; import com.evolveum.midpoint.repo.sql.data.common.ObjectReference; @@ -154,9 +157,20 @@ private JpaLinkDefinition parseMethod(Method method) { //todo implement also lookup for @Table indexes boolean indexed = method.isAnnotationPresent(Index.class); Class jaxbClass = getJaxbClass(method, jpaClass); + + ItemPathSegment itemPathSegment; + if (method.isAnnotationPresent(IdQueryProperty.class)) { + if (collectionSpecification != null) { + throw new IllegalStateException("ID property is not allowed to be multivalued; for method " + method); + } + itemPathSegment = new IdentifierPathSegment(); + } else { + itemPathSegment = new NameItemPathSegment(jaxbName); + } + JpaPropertyDefinition propertyDefinition = new JpaPropertyDefinition(jpaClass, jaxbClass, lob, enumerated, indexed); // Note that properties are considered to be embedded - linkDefinition = new JpaLinkDefinition(jaxbName, jpaName, collectionSpecification, true, propertyDefinition); + linkDefinition = new JpaLinkDefinition(itemPathSegment, jpaName, collectionSpecification, true, propertyDefinition); } return linkDefinition; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java new file mode 100644 index 00000000000..ebb1b47306f --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query2.definition; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Target of "#" (ID) queries. + * + * @author mederly + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface IdQueryProperty { + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index db71e82058e..ee88120337e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -57,8 +57,17 @@ public abstract class HibernateQuery { */ private List conditions = new ArrayList<>(); - private String orderByProperty; - private OrderDirection orderDirection; + class Ordering { + String byProperty; + OrderDirection direction; + + public Ordering(String byProperty, OrderDirection direction) { + this.byProperty = byProperty; + this.direction = direction; + } + } + + private List orderingList = new ArrayList<>(); public HibernateQuery(JpaEntityDefinition primaryEntityDef) { Validate.notNull(primaryEntityDef, "primaryEntityDef"); @@ -107,15 +116,24 @@ public String getAsHqlText(int indent) { sb.append("where\n"); Condition.dumpToHql(sb, conditions, indent+1); } - if (orderByProperty != null) { + if (!orderingList.isEmpty()) { sb.append("\n"); indent(sb, indent); - sb.append("order by ").append(orderByProperty); - if (orderDirection != null) { - switch (orderDirection) { - case DESCENDING: sb.append(" desc"); break; - case ASCENDING: sb.append(" asc"); break; - default: throw new IllegalStateException("Unknown ordering: " + orderDirection); + sb.append("order by "); + boolean first = true; + for (Ordering ordering : orderingList) { + if (first) { + first = false; + } else { + sb.append(", "); + } + sb.append(ordering.byProperty); + if (ordering.direction != null) { + switch (ordering.direction) { + case DESCENDING: sb.append(" desc"); break; + case ASCENDING: sb.append(" asc"); break; + default: throw new IllegalStateException("Unknown ordering: " + ordering.direction); + } } } } @@ -177,9 +195,8 @@ public String getPrimaryEntityAlias() { return getPrimaryEntity().getAlias(); } - public void setOrder(String propertyPath, OrderDirection direction) { - this.orderByProperty = propertyPath; - this.orderDirection = direction; + public void addOrdering(String propertyPath, OrderDirection direction) { + orderingList.add(new Ordering(propertyPath, direction)); } public abstract RootHibernateQuery getRootQuery(); From aededb61dc9f058969cb1ebebbd8aa7238e69769 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 3 Dec 2015 20:49:29 +0100 Subject: [PATCH 059/116] Fixed multi-stage campaigns. --- .../midpoint/certification/impl/AccCertUpdateHelper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java index 84b4c7d0a62..c170075a179 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; @@ -456,7 +457,9 @@ private void updateCases(AccessCertificationCampaignType campaign, AccessCertifi prismContext.getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(AccessCertificationCaseType.class) .findContainerDefinition(AccessCertificationCaseType.F_DECISION); ContainerDelta decisionDelta = ContainerDelta.createDelta(AccessCertificationCaseType.F_DECISION, decisionDef); - decisionDelta.addValuesToAdd(newDecisions); + for (AccessCertificationDecisionType newDecision : newDecisions) { + decisionDelta.addValueToAdd(new PrismPropertyValue<>(newDecision)); + } PropertyDelta reviewRequestedTimestampDelta = PropertyDelta.createModificationReplaceProperty( new ItemPath( From 2958d22ac9453c89462d13c1652ffd8e6054cebb Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 4 Dec 2015 00:22:15 +0100 Subject: [PATCH 060/116] Improving cert performance by skipping fetching cases each time. --- .../midpoint/prism/query/ObjectOrdering.java | 4 +++- .../midpoint/schema/SelectorOptions.java | 4 ++-- .../test/AbstractCertificationTest.java | 20 ++++++++++++++++++- .../test/BasicCertificationTest.java | 8 ++++---- .../test/CriticalRolesCertificationTest.java | 16 +++++++-------- .../test/RoleInducementCertificationTest.java | 16 +++++++-------- .../repo/sql/SqlRepositoryServiceImpl.java | 2 ++ .../common/RAccessCertificationCampaign.java | 5 ++--- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java index 169c5e4af00..a22b26b266f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectOrdering.java @@ -18,10 +18,12 @@ import com.evolveum.midpoint.prism.path.ItemPath; +import java.io.Serializable; + /** * @author mederly */ -public class ObjectOrdering { +public class ObjectOrdering implements Serializable { final private ItemPath orderBy; final private OrderDirection direction; diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java index 2dc5be62f65..19f6ac7a0da 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/SelectorOptions.java @@ -144,8 +144,8 @@ public static boolean hasToLoadPath(QName itemName, Collection> options) { List> retrieveOptions = filterRetrieveOptions(options); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java index 8e81e3b6326..31c5075c567 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java @@ -21,6 +21,8 @@ import com.evolveum.midpoint.model.test.AbstractModelIntegrationTest; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; @@ -28,6 +30,7 @@ import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.DummyResourceContoller; +import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; @@ -47,7 +50,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; @@ -57,12 +59,15 @@ import javax.xml.datatype.XMLGregorianCalendar; import java.io.File; +import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; +import static com.evolveum.midpoint.schema.RetrieveOption.INCLUDE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_CASE; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; @@ -332,4 +337,17 @@ protected void assertDecision2(AccessCertificationCaseType _case, AccessCertific // assertEquals("wrong enabled", enabled, _case.isEnabled()); } + protected AccessCertificationCampaignType getCampaignWithCases(String campaignOid) throws ConfigurationException, ObjectNotFoundException, SchemaException, CommunicationException, SecurityViolationException { + Task task = taskManager.createTaskInstance(AbstractModelIntegrationTest.class.getName() + ".getObject"); + OperationResult result = task.getResult(); + Collection> options = + Arrays.asList(SelectorOptions.create(F_CASE, GetOperationOptions.createRetrieve(INCLUDE))); + AccessCertificationCampaignType campaign = modelService.getObject(AccessCertificationCampaignType.class, campaignOid, options, task, result).asObjectable(); + result.computeStatus(); + TestUtil.assertSuccess(result); + return campaign; + } + + + } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java index 2f2089b1019..54dd34299d0 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java @@ -158,7 +158,7 @@ public void test020OpenFirstStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 1", campaign); assertStateAndStage(campaign, IN_REVIEW_STAGE, 1); @@ -426,7 +426,7 @@ public void test150CloseFirstStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 1", campaign); assertStateAndStage(campaign, REVIEW_STAGE_DONE, 1); @@ -459,7 +459,7 @@ public void test200StartRemediation() throws Exception { result.computeStatus(); TestUtil.assertInProgressOrSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign after remediation start", campaign); assertTrue("wrong campaign state: " + campaign.getState(), campaign.getState() == CLOSED || campaign.getState() == IN_REMEDIATION); @@ -468,7 +468,7 @@ public void test200StartRemediation() throws Exception { assertEquals("unexpected number of related tasks", 1, tasks.size()); waitForTaskFinish(tasks.get(0).getOid(), true); - campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + campaign = getCampaignWithCases(campaignOid); assertEquals("wrong campaign state", CLOSED, campaign.getState()); assertEquals("wrong campaign stage", 2, campaign.getStageNumber()); assertDefinitionAndOwner(campaign, certificationDefinition); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java index 85aef595dbb..3437e6a6faa 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java @@ -109,7 +109,7 @@ public void test010CreateCampaign() throws Exception { campaignOid = campaign.getOid(); - campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + campaign = getCampaignWithCases(campaignOid); display("campaign", campaign); assertEquals("Unexpected certification cases", 0, campaign.getCase().size()); assertStateAndStage(campaign, CREATED, 0); @@ -137,7 +137,7 @@ public void test020OpenFirstStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 1", campaign); assertStateAndStage(campaign, IN_REVIEW_STAGE, 1); @@ -226,7 +226,7 @@ public void test150CloseFirstStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 1", campaign); assertStateAndStage(campaign, REVIEW_STAGE_DONE, 1); @@ -265,7 +265,7 @@ public void test200OpenSecondStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 2", campaign); assertStateAndStage(campaign, IN_REVIEW_STAGE, 2); @@ -343,7 +343,7 @@ public void test250RecordDecisionsSecondStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 2", campaign); caseList = certificationManager.searchCases(campaignOid, null, null, task, result); @@ -403,7 +403,7 @@ public void test290CloseSecondStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign after closing stage 2", campaign); assertStateAndStage(campaign, REVIEW_STAGE_DONE, 2); @@ -442,7 +442,7 @@ public void test300StartRemediation() throws Exception { result.computeStatus(); TestUtil.assertInProgressOrSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign after remediation start", campaign); assertTrue("wrong campaign state: " + campaign.getState(), campaign.getState() == CLOSED || campaign.getState() == IN_REMEDIATION); @@ -451,7 +451,7 @@ public void test300StartRemediation() throws Exception { assertEquals("unexpected number of related tasks", 1, tasks.size()); waitForTaskFinish(tasks.get(0).getOid(), true); - campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + campaign = getCampaignWithCases(campaignOid); assertEquals("wrong campaign state", CLOSED, campaign.getState()); assertEquals("wrong campaign stage", 3, campaign.getStageNumber()); assertDefinitionAndOwner(campaign, certificationDefinition); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java index 509c4d8f7ff..2d136181cb2 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java @@ -107,7 +107,7 @@ public void test010CreateCampaign() throws Exception { campaignOid = campaign.getOid(); - campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + campaign = getCampaignWithCases(campaignOid); display("campaign", campaign); assertEquals("Unexpected certification cases", 0, campaign.getCase().size()); assertStateAndStage(campaign, CREATED, 0); @@ -192,7 +192,7 @@ public void test020OpenFirstStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 1", campaign); assertStateAndStage(campaign, IN_REVIEW_STAGE, 1); @@ -469,7 +469,7 @@ public void test150CloseFirstStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 1", campaign); assertStateAndStage(campaign, REVIEW_STAGE_DONE, 1); @@ -544,7 +544,7 @@ public void test200OpenSecondStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 2", campaign); assertStateAndStage(campaign, IN_REVIEW_STAGE, 2); @@ -663,7 +663,7 @@ public void test250RecordDecisionsSecondStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign in stage 2", campaign); caseList = certificationManager.searchCases(campaignOid, null, null, task, result); @@ -735,7 +735,7 @@ public void test290CloseSecondStage() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign after closing stage 2", campaign); assertStateAndStage(campaign, REVIEW_STAGE_DONE, 2); @@ -780,7 +780,7 @@ public void test300StartRemediation() throws Exception { result.computeStatus(); TestUtil.assertInProgressOrSuccess(result); - AccessCertificationCampaignType campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + AccessCertificationCampaignType campaign = getCampaignWithCases(campaignOid); display("campaign after remediation start", campaign); assertTrue("wrong campaign state: " + campaign.getState(), campaign.getState() == CLOSED || campaign.getState() == IN_REMEDIATION); @@ -789,7 +789,7 @@ public void test300StartRemediation() throws Exception { assertEquals("unexpected number of related tasks", 1, tasks.size()); waitForTaskFinish(tasks.get(0).getOid(), true); - campaign = getObject(AccessCertificationCampaignType.class, campaignOid).asObjectable(); + campaign = getCampaignWithCases(campaignOid); assertEquals("wrong campaign state", CLOSED, campaign.getState()); assertEquals("wrong campaign stage", 3, campaign.getStageNumber()); assertDefinitionAndOwner(campaign, certificationDefinition); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 9fb16cdd5c1..0f4c2203502 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -1252,6 +1252,8 @@ private void modifyObjectAttempt(Class type, String oi options = null; } + // TODO skip processing if there are no modifications other than row/case ones + // get object PrismObject prismObject = getObject(session, type, oid, options, true); // apply diff diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index 94c11a55309..d7d6b0f7e58 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -38,6 +38,7 @@ import javax.persistence.Entity; import javax.persistence.OneToMany; import javax.persistence.Table; +import javax.persistence.Transient; import javax.persistence.UniqueConstraint; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; @@ -75,9 +76,7 @@ public REmbeddedReference getDefinitionRef() { return definitionRef; } - @OneToMany(mappedBy = RAccessCertificationCase.F_OWNER, orphanRemoval = true) - @ForeignKey(name = "none") - @Cascade({org.hibernate.annotations.CascadeType.ALL}) + @Transient public Set getCase() { if (cases == null) { cases = new HashSet<>(); From 5307d500477521755cbdba6795bb711cc1f211b2 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 4 Dec 2015 00:55:46 +0100 Subject: [PATCH 061/116] Finally fixed shuffling of reviewer's decisions. --- .../impl/AccCertQueryHelper.java | 3 +- .../repo/sql/QueryInterpreter2Test.java | 53 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java index 81220e65954..ea134247f12 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertQueryHelper.java @@ -158,7 +158,8 @@ private ObjectQuery hackPaging(ObjectQuery query) { ObjectPaging paging1 = query.getPaging().clone(); ObjectOrdering primary = ObjectOrdering.createOrdering(newPath, oldDirection); ObjectOrdering secondary = ObjectOrdering.createOrdering(new ItemPath(PrismConstants.T_ID), OrderDirection.ASCENDING); // to avoid random shuffling if first criteria is too vague - paging1.setOrdering(primary, secondary); + ObjectOrdering tertiary = ObjectOrdering.createOrdering(new ItemPath(T_PARENT, PrismConstants.T_ID), OrderDirection.ASCENDING); // campaign OID + paging1.setOrdering(primary, secondary, tertiary); ObjectQuery query1 = query.clone(); query1.setPaging(paging1); return query1; diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index d293d17649b..cd1f8410d18 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -3010,6 +3010,59 @@ public void test920DecisionsNotAnswered() throws Exception { } } + @Test + public void test925DecisionsNotAnsweredOrderBy() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .exists(F_DECISION) + .block() + .item(AccessCertificationDecisionType.F_REVIEWER_REF).ref("123456") + .and().item(F_STAGE_NUMBER).eq().item(T_PARENT, F_CURRENT_STAGE_NUMBER) + .and().block() + .item(F_RESPONSE).isNull() + .or().item(F_RESPONSE).eq(NO_RESPONSE) + .endBlock() + .endBlock() + .asc(T_PARENT, F_NAME) + .asc(T_ID) + .asc(T_PARENT, T_ID) + .build(); + + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query); + String expected = "select\n" + + " a.fullObject\n" + + "from\n" + + " RAccessCertificationCase a\n" + + " left join a.decision d\n" + + " left join a.owner o\n" + + " left join a.owner o2\n" + + "where\n" + + " (\n" + + " (\n" + + " d.reviewerRef.targetOid = :targetOid and\n" + + " d.reviewerRef.relation = :relation\n" + + " ) and\n" + + " (\n" + + " d.stageNumber = a.currentStageNumber or\n" + + " (\n" + + " d.stageNumber is null and\n" + + " a.currentStageNumber is null\n" + + " )\n" + + " ) and\n" + + " (\n" + + " d.response is null or\n" + + " d.response = :response\n" + + " )\n" + + " )\n" + + "order by o.name.orig asc, a.id asc, o2.oid asc\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + // @Test // public void test930OrganizationEqualsCostCenter() throws Exception { // Session session = open(); From f09b6d8fcf37cf2fc5c8025f3512c3d245afac60 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 4 Dec 2015 09:54:51 +0100 Subject: [PATCH 062/116] Some comments. --- .../prism/query/builder/QueryBuilder.java | 28 +++++++++++++++++++ .../prism/query/builder/R_SimpleFilter.java | 23 --------------- 2 files changed, 28 insertions(+), 23 deletions(-) delete mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java index d3ce0de032f..004f023ed7b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java @@ -34,6 +34,34 @@ import java.util.List; /** + * Here is the language structure: + + Query ::= Filter? ('ASC(path)' | 'DESC(path)')* + + Filter ::= 'NOT'? SimpleFilter ( ('AND'|'OR') 'NOT'? SimpleFilter )* + + SimpleFilter ::= PrimitiveFilter | + 'BLOCK' Filter 'END-BLOCK' | + 'TYPE(type)' Filter | + 'EXISTS(path)' Filter + + PrimitiveFilter ::= 'ALL' | 'NONE' | 'UNDEFINED' | + ('ITEM(path)' ( ValueComparisonCondition | 'IS-NULL' | ( ItemComparisonCondition 'ITEM(path)') ) ) | + ('ID(values)') | ('OWNER-ID(values)') + + ValueComparisonCondition ::= 'EQ(value)' | 'GT(value)' | 'GE(value)' | 'LT(value)' | 'LE(value)' | 'STARTSWITH(value)' | 'ENDSWITH(value)' | 'CONTAINS(value)' | 'REF(value)' | 'ORG(value)' + ItemComparisonCondition ::= 'EQ' | 'GT' | 'GE' | 'LT' | 'LE' + + * + * It can be visualized e.g. using http://www.bottlecaps.de/rr/ui + * + * Individual keywords ('AND', 'OR', 'BLOCK', ...) are mapped to methods. + * Connections between these keywords are mapped to interfaces. + * It can be viewed as interfaces = states, keywords = transitions. (Or vice versa, but this is more natural.) + * The interfaces have names starting with S_ (for "state"). + * + * Interfaces are implemented by classes that aggregate state of the query being created. This is quite hacked for now... to be implemented more seriously. + * * @author mederly */ public class QueryBuilder { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java deleted file mode 100644 index a2e9c5ece7d..00000000000 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_SimpleFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.prism.query.builder; - -/** - * @author mederly - */ -public class R_SimpleFilter { -} From db8c5a33ff6b9e3e562c53b26f23aef4ed30de32 Mon Sep 17 00:00:00 2001 From: honchar Date: Fri, 4 Dec 2015 13:46:09 +0100 Subject: [PATCH 063/116] Associations editable panel. not finished yet --- .../web/component/form/ValueChoosePanel.java | 42 ++++++++--- .../web/component/prism/PrismValuePanel.java | 70 +++++++------------ .../component/ObjectSelectionPanel.java | 8 +++ 3 files changed, 65 insertions(+), 55 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java index 07b1cb55f8c..e55bf598f2a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java @@ -1,8 +1,11 @@ package com.evolveum.midpoint.web.component.form; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPage; import com.evolveum.midpoint.web.util.WebMiscUtil; import org.apache.wicket.Page; @@ -55,14 +58,22 @@ public class ValueChoosePanel extends SimplePanel { private static final String CLASS_MULTI_VALUE = "multivalue-form"; - public ValueChoosePanel(String id, IModel value, List values, boolean required, Class type) { - super(id, value); - setOutputMarkupId(true); + private Collection> options = null; - initLayout(value, values, required, type); + public ValueChoosePanel(String id, IModel value, List values, boolean required, Class type) { + this(id, value, values, required, type, null, null); } - private void initLayout(final IModel value, final List values, final boolean required, Class type) { + public ValueChoosePanel(String id, IModel value, List values, boolean required, Class type, + ObjectQuery query, Collection> options){ + super(id, value); + setOutputMarkupId(true); + this.options = options; + initLayout(value, values, required, type, query); + } + + private void initLayout(final IModel value, final List values, + final boolean required, Class type, ObjectQuery query) { WebMarkupContainer textWrapper = new WebMarkupContainer(ID_TEXT_WRAPPER); @@ -92,7 +103,7 @@ public void onClick(AjaxRequestTarget target) { textWrapper.add(edit); add(textWrapper); - initDialog(type, values); + initDialog(type, values, query); } @@ -108,19 +119,19 @@ protected void replaceIfEmpty(Object object) { } - protected void initDialog(final Class type, List values) { + protected void initDialog(final Class type, List values, ObjectQuery query) { if (FocusType.class.equals(type)){ initUserOrgDialog(); } else { - initGenericDialog(type, values); + initGenericDialog(type, values, query); } } // for ModalWindow treatment see comments in ChooseTypePanel - private void initGenericDialog(final Class type, final List values) { + private void initGenericDialog(final Class type, final List values, final ObjectQuery query) { final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { @@ -135,14 +146,23 @@ public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object getRealParent().choosePerformed(target, object); } + @Override + public Collection> getDataProviderOptions(){ + return options; + } + @Override public ObjectQuery getDataProviderQuery() { - return getRealParent().createChooseQuery(values); + if (query != null){ + return query; + } else { + return getRealParent().createChooseQuery(values); + } } @Override public boolean isSearchEnabled() { - return true; + return false; } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index 624b07b0177..7ba49bf0c56 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -29,10 +29,7 @@ import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.parser.QueryConvertor; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.*; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; @@ -414,45 +411,22 @@ private Panel createTypedInputComponent(String id) { ContainerWrapper containerWrapper = itemWrapper.getContainer(); if(containerWrapper != null && containerWrapper.getPath() != null){ if(ShadowType.F_ASSOCIATION.getLocalPart().equals(containerWrapper.getPath().toString())){ - Class typeFromName = null; PrismContext prismContext = item.getPrismContext(); if (prismContext == null) { prismContext = pageBase.getPrismContext(); } PrismContainerValue assocContainer = (PrismContainerValue)item.getParent(); - PrismProperty assocObjectClassItem = (PrismProperty)assocContainer.findItem(ShadowType.F_OBJECT_CLASS); - QName objectClassName = null; - if (assocObjectClassItem != null && assocObjectClassItem.getValues() != null - && assocObjectClassItem.getValues().size() > 0) { - objectClassName = (QName)((PrismPropertyValue)assocObjectClassItem.getValues().get(0)).getValue(); - } - + PrismProperty objectClassItem = (PrismProperty)assocContainer.findItem(ShadowType.F_OBJECT_CLASS); PrismProperty kindItem = (PrismProperty)assocContainer.findItem(ShadowType.F_KIND); - ShadowKindType shadowKindType = null; - if (kindItem != null){ - shadowKindType = kindItem.getValues() != null && kindItem.getValues().size() > 0 ? - (ShadowKindType)((PrismPropertyValue)kindItem.getValues().get(0)).getValue() : null; - } - PrismProperty intentItem = (PrismProperty)assocContainer.findItem(ShadowType.F_INTENT); - String intentValue = ""; - if (intentItem != null){ - intentValue = intentItem.getValues() != null && intentItem.getValues().size() > 0 ? - (String)((PrismPropertyValue)intentItem.getValues().get(0)).getValue() : ""; - } - - List> values = loadAssociationShadows(assocObjectClassItem, kindItem, intentItem); + PrismObject resource = ((ShadowType)containerWrapper.getObject().getObject().asObjectable()).getResource().asPrismObject(); + ObjectQuery query = getAssociationsSearchQuery(resource, + objectClassItem, kindItem, intentItem); + List> values = loadAssociationShadows(query); return new ValueChoosePanel(id, - new PropertyModel<>(model, "value"), values, false, ShadowType.class); -// return new TextDetailsPanel(id, new PropertyModel(model, baseExpression)){ -// -// @Override -// public String createAssociationTooltip(){ -// return createAssociationTooltipText(property); -// } -// }; + new PropertyModel<>(model, "value"), values, false, ShadowType.class, query, getAssociationsSearchOptions()); } } @@ -798,30 +772,38 @@ private void removeValue(AjaxRequestTarget target) { target.add(parent.getParent()); } - private List> loadAssociationShadows(PrismProperty objectClass, PrismProperty kind, - PrismProperty intent) { + private List> loadAssociationShadows(ObjectQuery query) { Task task = pageBase.createSimpleTask(OPERATION_LOAD_ASSOC_SHADOWS); OperationResult result = new OperationResult(OPERATION_LOAD_ASSOC_SHADOWS); List> assocShadows = null; try { - ObjectFilter andFilter = AndFilter.createAnd(EqualFilter.createEqual(new ItemPath(ShadowType.F_OBJECT_CLASS), objectClass), - EqualFilter.createEqual(new ItemPath(ShadowType.F_KIND), kind), - EqualFilter.createEqual(new ItemPath(ShadowType.F_INTENT), intent)); - ObjectQuery objectQuery = ObjectQuery.createObjectQuery(andFilter); - objectQuery.setFilter(andFilter); - Collection> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch()); - - assocShadows = pageBase.getModelService().searchObjects(ShadowType.class, new ObjectQuery(), null, task, result); + assocShadows = pageBase.getModelService().searchObjects(ShadowType.class, query, getAssociationsSearchOptions(), task, result); } catch (Exception ex) { LoggingUtils.logException(LOGGER, "Unable to load association shadow", ex); result.recordFatalError("Unable to load association shadow", ex); } finally { result.computeStatus(); } - return assocShadows; } + private ObjectQuery getAssociationsSearchQuery(PrismObject resource, PrismProperty objectClass, PrismProperty kind, + PrismProperty intent){ + ObjectFilter andFilter = AndFilter.createAnd( + EqualFilter.createEqual(new ItemPath(ShadowType.F_OBJECT_CLASS), objectClass), + EqualFilter.createEqual(new ItemPath(ShadowType.F_KIND), kind), + EqualFilter.createEqual(new ItemPath(ShadowType.F_INTENT), intent), + RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, resource)); + ObjectQuery query = ObjectQuery.createObjectQuery(andFilter); + return query; + } + + private Collection> getAssociationsSearchOptions(){ + Collection> options = new ArrayList>(); + options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createRaw())); + options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createNoFetch())); + return options; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ObjectSelectionPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ObjectSelectionPanel.java index fbaf98ce7ee..f82ab660954 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ObjectSelectionPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ObjectSelectionPanel.java @@ -22,6 +22,8 @@ import com.evolveum.midpoint.prism.query.AndFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.SubstringFilter; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -57,6 +59,7 @@ import javax.xml.namespace.QName; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.List; /** @@ -137,6 +140,10 @@ protected WebMarkupContainer createExtraContentContainer(String extraContentId, container.setOutputMarkupPlaceholderTag(true); return container; } + + public Collection> getDataProviderOptions(){ + return null; + } } public ObjectSelectionPanel(String id, Class type, ModalWindow modalWindow, Context context) { @@ -195,6 +202,7 @@ protected void clearSearchPerformed(AjaxRequestTarget target) { List, String>> columns = initColumns(); ObjectDataProvider provider = new ObjectDataProvider(pageBase, this.objectType); provider.setQuery(context.getDataProviderQuery()); + provider.setOptions(context.getDataProviderOptions()); TablePanel table = new TablePanel<>(ID_TABLE, provider, columns); table.setOutputMarkupId(true); addOrReplace(table); From ec849e4f4ebd45319fc817a9bbbaebf54711e1b9 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Fri, 4 Dec 2015 15:51:18 +0100 Subject: [PATCH 064/116] After-release build cleanup (MID-2744) --- gui/admin-gui/pom.xml | 16 +- infra/prism/pom.xml | 13 +- repo/audit-impl/pom.xml | 8 +- repo/repo-cache/pom.xml | 9 +- repo/security-impl/pom.xml | 8 +- repo/task-quartz-impl/pom.xml | 21 +- testing/systest/environment.properties | 25 - testing/systest/lib/groovy-ldap.jar | Bin 14415 -> 0 bytes testing/systest/pom.xml | 135 ------ testing/systest/runTests.sh | 6 - .../midpoint/testing/systest/Example.groovy | 31 -- .../midpoint/testing/systest/Helper.java | 31 -- .../src/test/groovy/check-enviroment.groovy | 139 ------ .../src/test/groovy/import-resources.groovy | 122 ----- .../src/test/resources/ctx-systest.xml | 41 -- .../src/test/resources/log4j.properties | 28 -- .../repo/connector-host-localhost.xml | 29 -- .../repo/resource-flatfile-remote.xml | 63 --- .../xml/resource-ldap1-dc=example.xml | 445 ------------------ testing/systest/src/test/scripts/deploy.sh | 1 - .../systest/src/test/scripts/install-ldap.sh | 54 --- testing/systest/src/test/scripts/restore.sh | 22 - .../src/test/scripts/systest-env-shutdown.sh | 8 - testing/systest/testng-integration.xml | 25 - testing/systest/testng-unit.xml | 19 - 25 files changed, 13 insertions(+), 1286 deletions(-) delete mode 100644 testing/systest/environment.properties delete mode 100644 testing/systest/lib/groovy-ldap.jar delete mode 100644 testing/systest/pom.xml delete mode 100755 testing/systest/runTests.sh delete mode 100644 testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Example.groovy delete mode 100644 testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Helper.java delete mode 100644 testing/systest/src/test/groovy/check-enviroment.groovy delete mode 100644 testing/systest/src/test/groovy/import-resources.groovy delete mode 100644 testing/systest/src/test/resources/ctx-systest.xml delete mode 100644 testing/systest/src/test/resources/log4j.properties delete mode 100644 testing/systest/src/test/resources/repo/connector-host-localhost.xml delete mode 100644 testing/systest/src/test/resources/repo/resource-flatfile-remote.xml delete mode 100644 testing/systest/src/test/resources/xml/resource-ldap1-dc=example.xml delete mode 100755 testing/systest/src/test/scripts/deploy.sh delete mode 100755 testing/systest/src/test/scripts/install-ldap.sh delete mode 100755 testing/systest/src/test/scripts/restore.sh delete mode 100755 testing/systest/src/test/scripts/systest-env-shutdown.sh delete mode 100644 testing/systest/testng-integration.xml delete mode 100644 testing/systest/testng-unit.xml diff --git a/gui/admin-gui/pom.xml b/gui/admin-gui/pom.xml index 500d4fbc607..67ee93f48f3 100644 --- a/gui/admin-gui/pom.xml +++ b/gui/admin-gui/pom.xml @@ -1,5 +1,5 @@ @@ -359,12 +355,6 @@ 3.4-SNAPSHOT runtime - - - - - - com.evolveum.midpoint.model report-impl @@ -448,8 +438,8 @@ 4.0.0.Final - + com.sun.xml.bind jaxb-xjc @@ -67,6 +63,7 @@ org.apache.santuario xmlsec + @@ -91,8 +88,9 @@ jackson-annotations - + - - - - - org.slf4j jcl-over-slf4j diff --git a/repo/repo-cache/pom.xml b/repo/repo-cache/pom.xml index 5678976c31b..a46ec5602b2 100644 --- a/repo/repo-cache/pom.xml +++ b/repo/repo-cache/pom.xml @@ -1,6 +1,6 @@ - - - - - diff --git a/repo/security-impl/pom.xml b/repo/security-impl/pom.xml index 814dc25d091..16e7e60d37a 100644 --- a/repo/security-impl/pom.xml +++ b/repo/security-impl/pom.xml @@ -1,6 +1,6 @@ - - - - - org.slf4j jcl-over-slf4j diff --git a/repo/task-quartz-impl/pom.xml b/repo/task-quartz-impl/pom.xml index 126ed8393a2..13f24938b9e 100644 --- a/repo/task-quartz-impl/pom.xml +++ b/repo/task-quartz-impl/pom.xml @@ -1,6 +1,6 @@ - - - com.evolveum.midpoint.repo repo-test-util diff --git a/testing/systest/environment.properties b/testing/systest/environment.properties deleted file mode 100644 index bc5051b51ca..00000000000 --- a/testing/systest/environment.properties +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2010-2013 Evolveum -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -midpoint.soap.url=http://localhost:8081/model - -ldap1.url=ldap://localhost:1389 -ldap1.binddn=cn=Directory Manager -ldap1.password=dmanager - -ldap2.url=ldap://localhost:2389 -ldap2.binddn=cn=Directory Manager -ldap2.password=dmanager diff --git a/testing/systest/lib/groovy-ldap.jar b/testing/systest/lib/groovy-ldap.jar deleted file mode 100644 index 12984815b616d610cb875d123530ad0e6b709d53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14415 zcmbt*Wq4aj(zO|7W@g9CF*7qWGc!Z%#H5&+nVC6;n3s0IBs;;imDMcA@2sn`6#%Rnn``<49_<#k00Fe_@6{44t7iWAP0Rd6`V=4^D z$m`UEP~LF;*QwU8Z}ivq->1q6$xDfgsi-o@iC@Z%jmpZ-oP+hj?9&gR=$WpDX^qGvNQ2VdQ9JVrljtCSv^a zL{lqgGZR+_XRrStLj3PUESw!2+`Vi~jU4}jG{rASTicsj{eMEZxmwx&9RlWW4`1O+ z|Mv?p5Reim5D>awScR;pkRmxVgNdz?i%X)aj>@bc`g0RC#0m%`N@YNvx~vQ{@dgy~ z9*v>SR9Hkiy`60!#aD7_aDje20BHKZSH6LNet| zV5TvN$aRayB3*N{GpYRY4N*kLIMczo@(V5`{cw0bAhL(ThQ;+b6>e?J$|{V>rRUo| z!W)*MspOjDjDc|8_{GKwqa&Qfy5`0VJFWE9U^+(Y(66BsD9q+5K%R-3oGkhRC?&qI zLt3bpgv5CqFjgI$jzip}uS1@F#8_?*k!B7|fO7q?+XjZJ5X{Ew)N zRh4MiV5=GI&XgW9?0fQyJQ*upVcYw+@DcMLqg8^Na9CAp@Bgx7f7==RD19Z3mtiKJS$pUZzpc8r5CXKR5U0kWj+14@4_VZDlc9@gk}Zoetqn(;dfELjy8OwIC-;K>-tVy$j&Lj(cGB~L zva=|co$Y)x%3hN%QIMezE3 z2mj~Z^1JW!^zvu6gTC&D;Qxc~u>9dW%B%LXg2;Tk101qQP7KNL%^HCe6ZA#IK%`F@Ktoy3G1;@{n8&LYS*J zh`IppQSXmyPj3RA&d{W5+twmdA}6{(7*@m0iHe3|E=;jKm8MF;_qj2j?Uo4D9eRa4 z7dzaNyqEJWOWn#?PoE`Us#z`e$3P1O1FVP+)k62|DR|8Mv1GeW64eLpq@aOrwm6e? z>%_Je8OOny_SyZEb8@QCS;bHj%3urFoVaSVn zNdXDC)upz&PaSeeMbpOOA$EP)g$x?sB!8#XqtFlgOj`MU$Rt&2G^`5pJ)t=T)#HM} zftY5fnSEpyf&yZGJ*(|ybLICoJ<`E?CQG<;Zn1V~TeOo}fsGf(-1b}SXSna$R0npT z|Je%C#Noo4U#-CIf3X7AzgvO)>Z=tT1+_@Y#?Qd-70noz#H+GkL<>o(ZGlqLOU7<_ z;W-clE;la7pg)%-hLv4RAstGn5#Xs}1Q2Vc@zI`Te9B1Oe9zzq>KQGLqvDxL;DV9B zWY7c9z z(>MPrmB_jfXyMd_*4g%CBw%7I&cdPtuybG;@mv`I6{*b!>sDOGxfU}frBK0hz&;i| zWR%Wkvi0P0`Xb{eO#Z?`Oh7;piJj`c+u7xl9Zkifrg18k`(+eh9Z`9L^gY#>ASAmwev77?qR@OdSpos4X8rdC|Bq_Q?x=}t2vAI%ZOU-# zp%I#wOXX=S9d1c&jX?Q|KvJLwDb~_kI#`N=<%-wvkutaWt zxf%>B0)*x8E+j^#3ERtSv&t4K~0;ciSD$s38S~~bIuW#HOOd{Q@EGW z#&ng;Ve5(K)h~G}vZ=K1yn8!76nhm}cxJu$2o-3!mQNk2o`!e+vjNDRlQea`hR`m^ z|6vqzq7|=$H4~QvO#C(69iN6q8|iG+`1gNH$;@x^%9TKQ@VjNR% z)O&{W4mS1x;BQJlNLxisC((@tRoHW)(8ItwX6a@q*Brs(e?|6jjv{F9B8>-+f7??j z1eJp>kHZ&dDSe!tRF3NX0-YvMr!jP9Wf|dsvemw|U;M)-%mz#8Bf!mZ%2WJ%VD%&(UW5Rv;}Grh6$q1vEWGKOdo{g zbTFHbazD9*9V#i|?V@J;RR%L~V7I5KS|sidb#qgjhtfcqS;2KpLLnsetK_KJiTBtD#+hCY(_Zkr zBSM^R!oMWU;oE-#-2)-G=p~AL=U>c${17Hjv~ZhqT6LUjle`8X3B#_+a3ze0zr;g0 z=u6Sh;X~yUytPL|V6>lE6Zx@TwL0Jkjbw$HGjHh2`26?d`0oJ`MM0^j<#ijpgZ>{p z;q4!upk}3lCxPsnZxhV+A%+>T&mCW4pqw_m8vlb7$Sy>BZ!JELV3indL4W!B_-R-` zfpVh44?ZWgnEaNEk%Pw)Rd4dd{89EK>sAfE_1S8l&4%Y6x09V9y8awN)RxL)l1>!B z*_N^`ZGcf}wT!Pw7*fFw>82*x zbs8JU&9@bGYuB{E!!3MQ5aG$qYqQM3s+ee)+4>%`w38KP1yBtf)Ltb1kgHAEiOLbSTuu(h4 z_wG=UxCpmtqv&mEm$vV4H>vKDc6r`a3mz+G~3q2ptHusZv zIrfjL>^hWQw2ln$jT&UaQ01aqg2Rs@+H%$fN|W=z8Yy#NcXesd%e0IZk#nde`37dO zW}JLm6j$lU!4&yM&Kcq>*7of%4uZNdyNRz|-hmZDZFmn>;qDf)c967LEW6#q=5vLS z@H)=eGfJ3c$B6K>JC%W?UgC{P<{PDt4(Z-n_V%OW+f|RQ%tYb&0XaK^bFR?rEaPrm z9KLx#M%~Pjq!R9RjaBzBsT&>YPxH3tE!^ijqOOA|>Y*e8IYwXkRnkq+v9C{(N^cLb z;%PLKT8ihN8^B{TeD)gO6zJD)0y^8T=H0d3p=ABh)`!_!^%=Aq%Z{mPV{5YBH$tP- z=J^~ok&`kqI*irIXNf&yn40%O0c=K*CI1oxDmfctWsS>oWq?`W zhH^&o0i92en1GZoYnU+5%y|&T^kNXkJd5-S;=(0VJ!B%INKB)h;FcEs9!!8=#Pf)n z^yt%;3zeIwOE)*LAjHg1BFCRo1Y9@F2-ulx%i9YB89|BW7O`hV5l{Y&^DSN+=ntp? z@Dv1#uM&1rP3i{Y zxnpt{SjhfoEVNUYRYdn=z&pZL zgJMC45X-E&4WJSdL~knH!Up1mysN89t~5QO&`Uk9W^*D=y90kz8gOY7L&40DyU&Ps znY5X7dDuNzJOe4J-3a8Dl}t%MjzvyHh9?eb2@nN=i$hiRvjmkj((Vb=AKS_el7KVE z;8kau+$ujxtTAE+e7U)5tx|I>FTlWGZIFfs_+HHI5Wzt|tg#1=BU@^*o5@Zg>|>ms zM}}>uEg|l?j+oQ)_A|wzxl7I7UK^*{0Ie?b$d1V>P2rUU%CPT0Cyml|7IA+Tn`OzQ z0D8nu2s5y+hMK);?cb7v51b`l?j_yykTse|SA>U?YoR@+>6Pt^%dvzr=bR?)DgELWXyCHcvBnq5udU(03gi+e& zZY-Yi<=Mh(1Bk?C*3;Q~DW+_qj5h!RV=dcw_}r;KS<%iN;>9+8E26KUX&z$p_+eq? z)Ns;xzMMfbof#s&60tmhzTU(6G!`J5?B@y{7`F&A+?@nyBu80G6!p7jbf4x4NGF$& zl8L#B#gFdCGprQ_*Q+%J&swT!26dpDTNm^=hWM-yGl|`yU*-|Mv8vjUYJxym2PU(b z(;n$7z6kqxM87WL%`X*pi_N$C-5;cM-C)WGaE-3PyA<^%uDInJ=!0if0JO)N{n<{I z4g4X;+K#S#3;WE#vgiV?6@js|KNvlIAy#4Gl(M(rET%M?ux$h! zVndoi)WfgwG7!9OQRJ5SwvEn7pItn|u2{sP7B{h=!2A^k?rrdkM66Jt3K; zKr6_cli?(FMN`~`0_N9VRDm$J0`Vkp0@Xo*=XnsF=e>+(nj=@8aYm55wB6NaobY~R z-414&kXrVBgX3qPet=g$p+-Mbb!VGunxH*u0h6~GAAe{(KjK9{PmBxPU1qO6hNr); zmwG7;dg-B^BbE$dX)sKU*gO2*+f2J)<278 znh_FDoL8wG`vmw{XXS8Xw$-zztrU8En z(aKGVeqL+QzA#eNf=_s!n>DevA)!%3=H?J)kMAq_xHUEF{HocF=>l#k1lXzg`B~xi zO+=QsqGyZPsA(13?3K-r{U*vF%kb3GirLo2JHHMFqk`)evm&1(?%5)*5{}fV)}s|S zdV4zm#)JK;&?ign>b3^YeZObVv%ssNBb0?`E@@SrnR; z$cY5=>w@9B1)yE6G4SoKcAe2`)BW4)`MEfW1_-f%Jf&DHe!KZr$f5KBavRRVPUjUk zqt8KEbM!33A|ztmbnb3J@a+6gHLtjhdt@rw$l1Vhm8f+@iXmr8E+&Y0 z!tCJ1u~6K>t=WvTPpE?k>~&2_XGX@vb$7|v7e+%c-;B*y`)@fFEG_RYDZ*cUzGK54 z%w0?^o@mCDb`WZ|wrvH*zMI&OL-7w_dT+|65p62CHwAmvTbA3&%i)J3!m%NUP5Y*BY!k{(|*6xNfKVS^g00A+h?2CjV}56Ip?~e@3-A zPuicOR|nbryF(*&W%yOedU0r?P3q)S2_0YtR5Sgn)I6aiMTE9`VN-CL+rl;iduaek zMbQYofwad8uPOPJE4^A0oGyX}$(XB7Kl+Grs>s6P%EBU|mI04#N5`Ev*@-H_s;qN| zos~SiC!cO06UY0+2*NWdJaxuWlY$-bX7N_t(N+k((h__*MHFduG?qo?bvAt-b&X`U zU2W&i)LLWO2`#k>%Nu?0a-trg*9HpSiWYJu&deUgsjh~nbQQw2gKv~}WuE&5 zL6Tw3tjgL1F2_rMq319$<*hzpj)VQoekVGQqUwmlAd!MDo8nEG!cv(-)xJ;L0;Z8v zcIvEtTA^I3ksvL3q(HdvzS4@)jlOVexkb9$#jz3G|H;OMrPRZEc)-;H$w2dh80IbN zJ1auywuX(IROuTi>Thv;u$lZAp^1Wa4kU03z2k7~jxG#U zN?W~-j53_j6Ek22NTW44Tfzyv_BcDTG3wNSXl$a*#w6|`$Vt}H` z?XoMOZ9(EG~!TvZmJlB5eWh<Wq#SW{M zw+&`U>KLW}1K8j;$xT~n7v7QsN6$6n#L}_tVz{E0YV**66{-XA3=<19GQ0j+JYNV${gv{V;dQ zZPO9Cy>mAjjodue@qWO7gJwlts=2~`JO|I^BcT?r&FUg0fcDH(Xx;>}Xlqj*p-1$g zquHqidBxK@8Z+f+r;|kLIzr`g$y5w!;1kAO?j(yCb2rjw2Ien>aq-6**^gtKll?_A zHjuFtA2}U3&P0|RwausiFU3(g-OI^6qQ5-fu(jTDZmR~ieYmjsr@s z2HkZ}XDA_%&?pMF2dY5i=^+mG`CNo}S>%0A05luPCag8Nq7+&Gb7>e5t?!)bJo{ty zRMZtUc{+nCaWFXAgV9VaNkBS5fR>L1T#NiSb)^!g#zB}(dD!eKJ}5~ z+{cv&AnDXIHIl7C&(;tXHH%wA8H(dH%=5xxusBPACe4vN_k(IaX-H;Ni^1hhG}l3FM$~lH1*gOz^^Ge3lAP% z@->k4!RWgoW|C`=Rji^-%YYq9&}}zC)cJDMxs+B3rmRu=S4$Kmy#j(PNW{r2I#CFP z$Z;3cp`w+Ca83ab4=%w9=MRPkbJO1)IaJMztRxJz1nAy0YAkJ4G;}**S&&@`;cg-j zIiqV!BHk(qkilET3YQg|%L`->Tmsdq+n!v(T{M&9%*R@(;LBmAT#WVSWjw3YJ4}^i zujAmZ$;AsHY#ie+l?LmU=X`AOHQZtl4&o5rGVnIt-@CC+PoaoxNKHrv&?Cv*H z>w@{TzlTu2Zxk}fi=TzA3VYktqENHpP`@L7ZwGcAjvul@WmmEj0y_%9scM{hzd#5gsr>+*}3k2K37_zqa*iN~ZAWi(t!e12aNHQBVkkRlDV zLo)0{n6fU5ZIEEa?n0TUO$2FE=w6}TGYe`u3j{jC=Zti~Ph{tP2S5Kxf|VFPm6;-= zUz<%Kaq7>0q}1&_X5_mzyxw-#P@CBoHppum@D1gS0z>pkB}MY!hAyEGSF{b>#gffI zZ8TX;ICIu$enRG;assH`c=sI`fnN98^xNLyFWb8jbzI&F35lhBEuj%x&zQ=0l-w!~ zPH)eJaEU&C%xKs+G@R`!R;X(fzdPdZh6#u4c;dhl%oua|ZW&47BvH>)PiA-{a%(uv z?uaj+f%-tZR(poFbjwpAkwNeU%CzM~u7Jsvm+R1L*U|BodCgT+6nmxtnsb>T;o$p_ z(6U1MX91-B11^Y5lj@$-oD-pImL9l6!??0Foq{CTkD>;)1HG#Fh=4@hO9*>aZ$6mR zUBl@GFMMypAd$gsX`gt(JH*D(uNi53A3FNJmS^(sT+wDc)3rSi{c{$n|J{d`;_jivD$yWtP+!e5kxf8ZC$Ihb0RTbUTSS~=LOdO4c?o>6A1tUJso;`1dpHPp0z zXEsVt&sL#U;bA|3H^uR1=r(Lxk`jJb)>Tu`1OW&85|1=8hZAW&`K&asc_L{F%eYI~ zaggPspfLHgzWVw%{UcONZ#ax7Z`ckq3(E{k165MY-a4j%R~|7Y#k-MVR!G>W)&TNB zI~*>kTulbnW7Q6Qo#s~cU0)f8l@9gZTW_+C^~?6{AuDaYr^Lkug%jZ3YL*Ynx26lg zcAe5&c>vUpMkihRBun(KEplzns}b5!%?M9bY$8tzxRTMx0J;NXHd$gOCdklMP0g zJ6^58W_7Vu7EIoE>>-JT%qT{pkNWMCB_x;_=-lzbJy*|iWOa-HbQzET1%uXF?^CE* zMvRX1GGmMY6bmF$4VM;wQ9^s-d*O;V=t8^_UjWk|=tH(Yl!CUANP+4AUPx&oP~INx zV3%nn4`{MYb}@+5NJV^n`KgZ2Lztt>{AzRvu)kKvS1~hkHnIG(inppxCWgK)#;^`M z4uZolAT*Z4l8H#N>k9xNZbjtj&cTdCG*eoo0gHHM*SB|`F5o|(LwdQC$^>xA5E%I0 zGCqQ2cWz+6>OXbqQ^xlHi8)s?$HeV?4{1oK2S7-SB?L8%^agskpo3g_Za$Exib zT>Rt}n9i|lYQCb>rE{X$r_8f4z_UgN-$E}Om5=7(d8eoUoiFR@a|jB*AF*(#${x}W zVT@P|CK|&+0&prgDyM2nL$wctgJv6JxI_r{CGv1bVC>jEv}NVY^lvT7lCo$$ zql~_q08pAOlc`fO8wvP|lje8Ql4xcjjx}!7;a& zr;q-wSz&mX^i2(4y2YKw=+XA1zC-rTOjPfZ@`(O=zj8L&s71liGYt+_e`u@2ut~@Fjy>#Du@pT*6>3mkD z6V)Wv=MHO>%bVhzeX}m8VGVX@<-AB))4omE@MKk=trj?p8Z=1n9}0U|dC-=9 zoj6Q7v7AL(K*WIi+FotMwbcWyhRN54Sd`SHTAxQ>!6FMa&tJ?9F`4Cx@0JXsHflCb zGi`#ac>{`N8bNqOdvy+u(%_UhRS^l_MUU@V zUPDC3X8eO`R3dJB)5!`+Z}{9-H_w4zSuBkQ`ete{6a0rIi+6|ww&$Vn9TtG$W8Ahd ze;zs6TVCz{Exv-Jv+auuP#|jb{JCe6-&;_`4?i|?^}Zc< zaEIPHa+gvwK0aBBzQ#TG11!}94+)!;a$GV*p>YmTSx1>a?n!~4O2vXLjqgDM=Y2C- zEJeFx{Kl-y*{6f7hql|vO`=ZFgmY3vlxTEbaeZ-lV38pXX=Q!F<7C$sO|bL|HyOS5q)akm>*x6z~}DU zd!?XuakEf0IuC1c@B(kHUCm2zA{uzJRmSq63!ceR&oB!>KcsqjOYi{=du_2XB*%|U zI}E7;)dH_%p)e9BKEgoLPoE_Yw1#b1r_;~88?ffB9hyWXs<^Nd4)nU*G_;d5HMA?; z6!RonWhZsHHFu{$dalq}@lm$7{l9QmLueQylwUDdppBwl6v=jdCUJ({RvFrLy^AcR zlpxe?Oz_vdL;Q-mlStJgBg}_YDV#&~L7U26msor05$=aeNh=!7SzJHgTDEo(%%?)t zJFp)nRN>p8O+~W~R1^+_0whhd%t9@KkNDCWIkt5z3MfJH0{1*J3GNBy{PavF73R+FdZ1&K9<_IVywM`WVHY}q)EEr4`~xa#2@Uz$N~Xj zfsbA2ugCoeKm`SU+{#Pg~zua1cL zN(`0w1xNfFJyq1o`Hy>~>L6$2s9-0*1`7#i z45)^fyN1O^kK`qXy93Gn!X8suqq-z_!T^(1dcomX-|jdcu38}dz3hFDLEa5rtRTqs zmb%?7Z);~(b(_WK=es-DE;U&iOQDSX%-x6prk%H(<)lF_G!whR2&m3+s?+}R7+6kH zVWarKFsdpl2uHc7DjBE1-J$^O9p{`N4nXW`lHCtqz_zG!TyELsa2f!C zYxX@atHZ=S&gx|_pNvg48rh|>6tcBe^3&NT;R8lhs#xEsQOhI)`K%T?hmhx@F8Niey(Gxy6E);X$cfnpJ7F@y|6p__U z<$NR2fJkd>k!;|gXWn+{l`S2#LR*z4PA#v2J>M?&B9s3Cz-n+DCy&_tU`%g{Ytbo5 z{X$ELY5%06F?>2m1ifjNi5$!Xcs~N6Ry05hfsA1vY1W)c%FqKpJ>Sev$hbFHENtCH6aH9>t0p}Uy?xCIupatk6#p_+_VISW{wgFQX_B?! zP27Wb!dy;Ai(#wqelW7a({h0SB&@@n)A-i2{OnU>AmUnj8$sDTIxlNYvF9oTj_M|k zlYW|g=Q&KpNWH$DiMeDPmWT_f3$eN0C&Ie-!x1bBvLBmzJ*PN}nuwP*2tw*mnVKOswm{t5aZkK}99<^xGIEief`11Ya8EBCD#q+1KOOInc z!DI9%HPJIy!P?3Mf9{$20uc(@N3efR@C-B`<6>X;pVU`BWBdgl`x}2-?Uls+yDtSR z>o9@~p+C#Foy_Ppm&xcIDQj2SdaA~51^4X+_<@QWvMggKp8|7^L&I3EREA5X#i$)f$GB z`GY19H1L_bne4KaCOervCrER%9R?i}^-(w(YkXb;_4*J42cIdu%ACYEXjFFci5rT! zz*tiPii}&FxyV>o0uwE${Xhf3iH-(ZJH}Cx9J8{kVNf0lye7AGzr>Yphw2m0#Pz0a^lc zfcZ0McgVSEn~>#pMIf0|gxq?7y|6H=_VkTYdnDBkzQ!5KvWc{7$2r6vYJIQ-72fRI zJ{T8i?NSo?7Ey;96`U}P*;?E*(xnb>pHBhmbaVAPZkk|ciZY;J=-~gpv*Ps;zYb)O z6QSR}|K2?Dd!NOhqW`+n;x~ccMu9)=>*wD^|Do^VKPmsMH{$p4oAS2T%ilXC{?z%e zdnNvoSpP%f@0}C>UhucxiQmU>s-Rx2`(KtV{?lrS|3vuPt>XH35dTp5_)loR^;Y~o zep`^oFQEO=Y4PuW<3B^T{sQD5ofm&X{_Eb0Ki65{|MUxx|JaG~*YE$=%=EvIxn7Am z|MG$S!`=KF@*h0)pOJrNJO70&@JjmoCFDQ2&p#voOr!k^S@5+C@k_{mkZONM{+X8e z7qT?q7m@!UDgKQ7Gu`PgWLe~2ME-;P^fU6$43fW)RnUG7`S%#{Gw#nd#lLVng8wH& z_!<6{SpH8(>c8MIUt6#K8~iUGuzyzi^BLnWrQWYcj{m0grxS;w4CHG%00M&X`r3ZI K()=xR0{MSbOwUOG diff --git a/testing/systest/pom.xml b/testing/systest/pom.xml deleted file mode 100644 index b0baf940adb..00000000000 --- a/testing/systest/pom.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - midPoint Testing - System testing - 4.0.0 - com.evolveum.midpoint.testing - systest - 1.10-SNAPSHOT - - Evolveum - http://www.evolveum.com - - - https://github.com/Evolveum/midpoint.git - git@github.com:Evolveum/midpoint.git - https://fisheye.evolveum.com/browse/midPoint - - - - evolveum - Evolveum - http://nexus.evolveum.com/nexus/content/groups/public - - - - 1.7 - - - - Apache License v2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - Atlassian JIRA - http://jira.evolveum.com/ - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - true - 128m - 768m - true - true - - - - org.apache.maven.plugins - maven-resources-plugin - - UTF-8 - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.9 - - once - - - false - - testng.xml - - - - - org.apache.maven.surefire - surefire-testng - 2.9 - - - - - org.codehaus.gmaven - gmaven-plugin - 1.3 - - - - generateStubs - compile - generateTestStubs - testCompile - - - - - true - true - true - .groovy - - - - - - - org.codehaus.gmaven.runtime - gmaven-runtime-1.6 - 1.3 - - - - org.testng - testng - 6.1.1 - test - - - - diff --git a/testing/systest/runTests.sh b/testing/systest/runTests.sh deleted file mode 100755 index ccd97c90d7e..00000000000 --- a/testing/systest/runTests.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -#Test enviroment -CLASSPATH="../../infra/schema/target/schema-2.1-SNAPSHOT.jar:../../gui/admin-gui/target/idm/WEB-INF/lib/xml-resolver-1.2.jar:./lib/groovy-ldap.jar:../../gui/admin-gui/target/idm/WEB-INF/lib/commons-io-2.0.1.jar:../../gui/admin-gui/target/idm/WEB-INF/lib/cxf-common-utilities-2.4.3.jar:../../gui/admin-gui/target/idm/WEB-INF/lib/commons-lang-2.6.jar" -groovy -cp "$CLASSPATH" -d ./src/test/groovy/check-enviroment.groovy -groovy -cp "$CLASSPATH" -d ./src/test/groovy/import-resources.groovy diff --git a/testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Example.groovy b/testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Example.groovy deleted file mode 100644 index 5f881b6895d..00000000000 --- a/testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Example.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2010-2013 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Generated from archetype; please customize. -// - -package com.evolveum.midpoint.testing.systest - -/** - * Example Groovy class. - */ -class Example -{ - def show() { - println 'Hello World' - } -} diff --git a/testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Helper.java b/testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Helper.java deleted file mode 100644 index 9f341099459..00000000000 --- a/testing/systest/src/main/groovy/com/evolveum/midpoint/testing/systest/Helper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2010-2013 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Generated from archetype; please customize. -// - -package com.evolveum.midpoint.testing.systest; - -/** - * Example Java class. - */ -public class Helper -{ - public void help(final Example example) { - example.show(); - } -} diff --git a/testing/systest/src/test/groovy/check-enviroment.groovy b/testing/systest/src/test/groovy/check-enviroment.groovy deleted file mode 100644 index dbb4a0920ee..00000000000 --- a/testing/systest/src/test/groovy/check-enviroment.groovy +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010-2013 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.io.File -import java.net.MalformedURLException -import java.net.URL -import javax.xml.namespace.QName -import javax.xml.ws.Holder -import javax.jws.WebMethod -import javax.jws.WebParam -import javax.jws.WebResult -import javax.jws.WebService -import javax.jws.soap.SOAPBinding -import javax.xml.bind.annotation.XmlSeeAlso -import com.evolveum.midpoint.xml.ns._public.model.model_1_wsdl.ModelService -import com.evolveum.midpoint.xml.ns._public.model.model_1_wsdl.ModelPortType -import com.evolveum.midpoint.xml.ns._public.common.common_1.PropertyReferenceListType -import com.evolveum.midpoint.xml.ns._public.common.common_1.SystemConfigurationType -import com.evolveum.midpoint.xml.ns._public.common.common_1.ObjectType -import com.evolveum.midpoint.xml.ns._public.common.common_1.OperationResultType - - -import org.apache.directory.groovyldap.* - - -boolean fail=false -//######################### common initialization ########################### -def config = new Properties() -new File("environment.properties").withInputStream { - stream -> config.load(stream) -} - -//Define webservice name and listener -QName SERVICE_NAME = new QName("http://midpoint.evolveum.com/xml/ns/public/model/model-1.wsdl", "modelService") -URL wsdlURL = new URL (config['midpoint.soap.url']+"?WSDL") - -//initialize webservice -ModelService ss = new ModelService(wsdlURL,SERVICE_NAME); -//Get modelWebservice object -ModelPortType model = ss.getModelPort() - -//LDAP1 connect (http://directory.apache.org/api/groovy-ldap.html) -//http://directory.apache.org/api/2-groovy-ldap-user-guide.html -ldap1 = LDAP.newInstance( config['ldap1.url'], config['ldap1.binddn'] , config['ldap1.password'] ) -ldap2 = LDAP.newInstance( config['ldap2.url'], config['ldap2.binddn'] , config['ldap2.password'] ) - -//######################### end of common initialization ########################### - -// Try to delete unexisting object -try { - println model.deleteObject("http://midpoint.evolveum.com/xml/ns/public/common/common-1.xsd#SystemConfigurationType", "00000000-0000-0000-0000-000000000002000") - println "SOAP Webservice on " + config['midpoint.soap.url'] + " connect \tFAIL" - fail=true -} catch ( Exception e) { - assert e.getMessage() == "Object not found. OID: 00000000-0000-0000-0000-000000000002000" - println "SOAP Webservice on " + config['midpoint.soap.url'] + " connect \tPASS" -} - -try { - Holder obj = new Holder() - Holder result = new Holder() - PropertyReferenceListType props = new PropertyReferenceListType() - - model.getObject("http://midpoint.evolveum.com/xml/ns/public/common/common-1.xsd#SystemConfigurationType", "00000000-0000-0000-0000-000000000001", props, obj, result) - - //println "OBJECT:" + obj.value - //println "RESULT:" + result.value - - println "SOAP Webservice on " + config['midpoint.soap.url'] + " getObj\tPASS" -} catch ( Exception e) { - println e.getMessage() - println "SOAP Webservice on " + config['midpoint.soap.url'] + " getObj\tFAIL" - fail=true -} - - - -//test tree exstincence -if ( ldap1.exists ('dc=example,dc=com')) { - println "LDAP1 " + config['ldap1.url'] +" dc=example,dc=com \t\tPASS" -} else { - println "LDAP1 " + config['ldap1.url'] +" dc=example,dc=com \t\tFAIL" - fail=true -} -if ( ldap1.exists ('dc=systest,dc=com')) { - println "LDAP1 " + config['ldap1.url'] +" dc=systest,dc=com \t\tPASS" -} else { - println "LDAP1 " + config['ldap1.url'] +" dc=systest,dc=com \t\tFAIL" - fail=true -} -if ( ldap1.exists ('cn=changelog')) { - println "LDAP1 " + config['ldap1.url'] +" cn=changelog \t\tPASS" -} else { - println "LDAP1 " + config['ldap1.url'] +" cn=changelog \t\tFAIL" -} - -if ( ldap2.exists ('dc=example,dc=com')) { - println "LDAP2 " + config['ldap2.url'] +" dc=example,dc=com \t\tFAIL" - fail=true -} else { - println "LDAP2 " + config['ldap2.url'] +" dc=example,dc=com \t\tPASS" -} -if ( ldap2.exists ('dc=systest,dc=com')) { - println "LDAP2 " + config['ldap2.url'] +" dc=systest,dc=com \t\tPASS" -} else { - println "LDAP2 " + config['ldap2.url'] +" dc=systest,dc=com \t\tFAIL" - fail=true -} -if ( ldap2.exists ('cn=changelog')) { - println "LDAP2 " + config['ldap2.url'] +" cn=changelog \t\tPASS" -} else { - println "LDAP2 " + config['ldap2.url'] +" cn=changelog \t\tFAIL" - fail=true -} - - -//Calculate result -if (fail) { - println "Systest enviroment check failed." - System.exit(1) -} else { - - println "Systest enviroment check passed." - System.exit(0) -} - diff --git a/testing/systest/src/test/groovy/import-resources.groovy b/testing/systest/src/test/groovy/import-resources.groovy deleted file mode 100644 index 469b64ef32f..00000000000 --- a/testing/systest/src/test/groovy/import-resources.groovy +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2010-2013 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.io.File -import java.net.MalformedURLException -import java.net.URL -import javax.xml.namespace.QName -import javax.jws.WebMethod -import javax.jws.WebParam -import javax.jws.WebResult -import javax.jws.WebService -import javax.jws.soap.SOAPBinding -import javax.xml.bind.annotation.XmlSeeAlso -import com.evolveum.midpoint.xml.ns._public.model.model_1_wsdl.ModelService -import com.evolveum.midpoint.xml.ns._public.model.model_1_wsdl.ModelPortType -import com.evolveum.midpoint.xml.ns._public.common.common_1.* -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_1.* -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_1.ActivationCapabilityType - -import com.evolveum.midpoint.xml.ns._public.common.annotation_1.* -import com.evolveum.midpoint.xml.ns._public.common.common_1.* -import com.evolveum.midpoint.xml.ns._public.common.fault_1.* -import com.evolveum.midpoint.xml.ns._public.common.fault_1_wsdl.* -import com.evolveum.midpoint.xml.ns._public.connector.icf_1.connector_schema_1.* -import com.evolveum.midpoint.xml.ns._public.connector.icf_1.resource_schema_1.* -import com.evolveum.midpoint.xml.ns._public.model.model_1_wsdl.* -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_1.* -import com.evolveum.midpoint.xml.ns._public.resource.resource_schema_1.* -import com.evolveum.midpoint.schema.util.JAXBUtil -import javax.xml.bind.JAXBContext -import javax.xml.bind.JAXBElement -import javax.xml.bind.JAXBException -import javax.xml.bind.Unmarshaller -import javax.xml.ws.Holder - -import org.apache.directory.groovyldap.* - - -//######################### common initialization ########################### -def config = new Properties() -new File("environment.properties").withInputStream { - stream -> config.load(stream) -} - -//Define webservice name and listener -QName SERVICE_NAME = new QName("http://midpoint.evolveum.com/xml/ns/public/model/model-1.wsdl", "modelService") -URL wsdlURL = new URL (config['midpoint.soap.url']+"?WSDL") - -//initialize webservice -ModelService ss = new ModelService(wsdlURL,SERVICE_NAME); -//Get modelWebservice object -ModelPortType model = ss.getModelPort() - -//LDAP1 connect (http://directory.apache.org/api/groovy-ldap.html) -//http://directory.apache.org/api/2-groovy-ldap-user-guide.html -ldap1 = LDAP.newInstance( config['ldap1.url'], config['ldap1.binddn'] , config['ldap1.password'] ) -ldap2 = LDAP.newInstance( config['ldap2.url'], config['ldap2.binddn'] , config['ldap2.password'] ) - -//######################### end of common initialization ########################### - -//Search for all Connector types try to find ldap connector ref -Holder result = new Holder() -Holder objs = new Holder() - -PagingType paging = new PagingType() -try { - model.listObjects("http://midpoint.evolveum.com/xml/ns/public/common/common-1.xsd#ConnectorType",paging,objs,result) -} catch ( Exception ex ) { - println "Error while listObjs: " + ex.getMessage() - println ex.printStackTrace() -} - -def ldapConnectorRefOid -for(def obj in objs.value.getObject()) { - if ( obj.name == "ICF org.identityconnectors.ldap.LdapConnector" ) { - ldapConnectorRefOid = obj.oid - } -} -//add resource ldap1 -ResourceType object = ((JAXBElement) JAXBUtil.unmarshal(new File("src/test/resources/xml/resource-ldap1-dc=example.xml"))).getValue(); - -object.getConnectorRef().setOid(ldapConnectorRefOid); - -Holder newOid = new Holder() - - -try { - model.addObject(object,newOid,result); -} catch ( Exception ex ) { - //println "Error: " + ex.getMessage() - println ex.printStackTrace() -} - -println "Inserting object: " + object.getName() -println "oid: " + newOid.value -println "Result: " + result.value - -ldap1Oid = newOid.value - - -try { - def res = model.testResource(ldap1Oid) - println res -} catch ( Exception ex ){ - println "Error test connection to ldap1 : " + ex.getMessage() -} - - - diff --git a/testing/systest/src/test/resources/ctx-systest.xml b/testing/systest/src/test/resources/ctx-systest.xml deleted file mode 100644 index bcb5ddb342a..00000000000 --- a/testing/systest/src/test/resources/ctx-systest.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - diff --git a/testing/systest/src/test/resources/log4j.properties b/testing/systest/src/test/resources/log4j.properties deleted file mode 100644 index f9faa3df881..00000000000 --- a/testing/systest/src/test/resources/log4j.properties +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2010-2013 Evolveum -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -####################################################### -# This logger setting is only for testing. # -# do not use it in production. Just in unit tests # -####################################################### - -log4j.rootLogger = TRACE, X -log4j.appender.X=org.apache.log4j.FileAppender -log4j.appender.X.file=./target/test.log -log4j.appender.X.layout=org.apache.log4j.PatternLayout -log4j.appender.X.layout.conversionPattern=%d{ISO8601} [%t] %p (%c): %m%n - -log4j.logger.org.springframework=WARN diff --git a/testing/systest/src/test/resources/repo/connector-host-localhost.xml b/testing/systest/src/test/resources/repo/connector-host-localhost.xml deleted file mode 100644 index 7b8d27677c6..00000000000 --- a/testing/systest/src/test/resources/repo/connector-host-localhost.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - ICF Connector server on localhost:8759 - localhost - 8759 - secret - diff --git a/testing/systest/src/test/resources/repo/resource-flatfile-remote.xml b/testing/systest/src/test/resources/repo/resource-flatfile-remote.xml deleted file mode 100644 index ed0f425f48e..00000000000 --- a/testing/systest/src/test/resources/repo/resource-flatfile-remote.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - Remote Flatfile - - - - - - - - org.identityconnectors.flatfile.FlatFileConnector - - - - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-aaeeffeeffaa - - - - - - - /tmp/flatfile-connector - - - - - - - diff --git a/testing/systest/src/test/resources/xml/resource-ldap1-dc=example.xml b/testing/systest/src/test/resources/xml/resource-ldap1-dc=example.xml deleted file mode 100644 index 09fa250c389..00000000000 --- a/testing/systest/src/test/resources/xml/resource-ldap1-dc=example.xml +++ /dev/null @@ -1,445 +0,0 @@ - - - - - - - - - LDAP1 dc=example - - - - - - - - org.identityconnectors.ldap.LdapConnector - - - - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff - - - - - - - 1389 - localhost - dc=example,dc=com - cn=directory manager - dmanager - uid - ds-pwp-account-disabled - - - - - - 120000 - 1 - 10 - 10 - 150000 - - - 100 - - - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - - - - - - - - - - - - - Default Account - - - ri:AccountObjectClass - - - - - - Distinguished Name - - - create - read - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - concat('uid=', - $i:user/c:name, ',ou=people,dc=example,dc=com') - - - - - - - - - - - - - Entry UUID - - - read - - - - - - - - - - - Common Name - create - read - update - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:fullName - - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:fullName - - - - - - - - Surname - create - read - update - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:familyName - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:familyName - - - - - - - Given Name - create - read - update - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:givenName - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:givenName - - - - - - - Login Name - create - read - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:name - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:name - - - - - - - - - - Created by IDM - - - - - - - \p{C} - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace - my="http://whatever.com/my"; - $i:user/i:extension/my:description - - - - - - - - - - - - - - - - - - middle of nowhere - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace my="http://myself.me/schemas/whatever"; - - if ($my:config/i:extension/my:locations/my:location[@key=$i:user/i:locality]) then - $my:config/i:extension/my:locations/my:location[@key=$i:user/i:locality] - else - $my:defaultLocation - - - - - - - true - - - - - - - - - ri:ds-pwp-account-disabled - - true - - - - - - - - - - - - - true - - - - - - - . - - c:name - - $i:account/i:attributes/dj:uid - - - - - - - - - - confirmed - - - - deleted - - - - missing - - - - found - - - - unassigned - - - - unmatched - - - - - - - - - - diff --git a/testing/systest/src/test/scripts/deploy.sh b/testing/systest/src/test/scripts/deploy.sh deleted file mode 100755 index 54150b75fef..00000000000 --- a/testing/systest/src/test/scripts/deploy.sh +++ /dev/null @@ -1 +0,0 @@ -cp ../../gui/admin-gui/target/idm.war /opt/tomcat/webapps diff --git a/testing/systest/src/test/scripts/install-ldap.sh b/testing/systest/src/test/scripts/install-ldap.sh deleted file mode 100755 index ba6276345ee..00000000000 --- a/testing/systest/src/test/scripts/install-ldap.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -export JAVA_HOME=/opt/java/ -export PATH=/opt/java/bin:$PATH - -export LDAP_INST=~mamut/install/OpenDJ-2.4.4.zip - - -/opt/ldap1/OpenDJ-2.4.4/bin/stop-ds -/opt/ldap2/OpenDJ-2.4.4/bin/stop-ds -/opt/ldap1/OpenDJ-2.4.4/bin/status -D "cn=Directory Manager" -j rootUserPasswordFile -s | grep "Server Run Status" | grep Stopped -/opt/ldap2/OpenDJ-2.4.4/bin/status -D "cn=Directory Manager" -j rootUserPasswordFile -s | grep "Server Run Status" | grep Stopped -rm -rf /opt/ldap1/ -rm -rf /opt/ldap2/ - -unzip $LDAP_INST -d /opt/ldap1/ -unzip $LDAP_INST -d /opt/ldap2/ -/opt/ldap1/OpenDJ-2.4.4/setup -i --no-prompt -D "cn=Directory Manager" -a -p 1389 --adminConnectorPort 14444 -j rootUserPasswordFile -h localhost -b "dc=example,dc=com" -b "dc=systest,dc=com" -/opt/ldap2/OpenDJ-2.4.4/setup -i --no-prompt -D "cn=Directory Manager" -a -p 2389 --adminConnectorPort 24444 -j rootUserPasswordFile -h localhost -b "dc=systest,dc=com" -/opt/ldap1/OpenDJ-2.4.4/bin/status -D "cn=Directory Manager" -j rootUserPasswordFile -s | grep "Server Run Status" | grep Started -/opt/ldap2/OpenDJ-2.4.4/bin/status -D "cn=Directory Manager" -j rootUserPasswordFile -s | grep "Server Run Status" | grep Started - -/opt/ldap1/OpenDJ-2.4.4/bin/dsreplication enable \ - --host1 localhost \ - --port1 14444 \ - --bindDN1 "cn=directory manager" \ - --bindPassword1 `cat rootUserPasswordFile` \ - --replicationPort1 18989 \ - --host2 localhost \ - --port2 24444 \ - --bindDN2 "cn=directory manager" \ - --bindPassword2 `cat rootUserPasswordFile` \ - --replicationPort2 28989 \ - --adminUID admin --adminPassword password \ - --baseDN "dc=systest,dc=com" -X -n - - -/opt/ldap1/OpenDJ-2.4.4/bin/dsreplication initialize --baseDN "dc=systest,dc=com" \ - --adminUID admin --adminPassword password \ - --hostSource localhost --portSource 14444 \ - --hostDestination localhost --portDestination 24444 -X -n - -/opt/ldap1/OpenDJ-2.4.4/bin/dsreplication status --baseDN "dc=systest,dc=com" \ - --adminUID admin --adminPassword password -X -n | grep -v "\[.\]" - -cd /opt/ -/opt/ldap1/OpenDJ-2.4.4/bin/stop-ds -/opt/ldap2/OpenDJ-2.4.4/bin/stop-ds -zip -r ldaps.zip ./ldap1 ./ldap2/ - -rm /tmp/opends-setup* -rm /tmp/opends-replication* - - diff --git a/testing/systest/src/test/scripts/restore.sh b/testing/systest/src/test/scripts/restore.sh deleted file mode 100755 index e35d93be515..00000000000 --- a/testing/systest/src/test/scripts/restore.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# shutdown and restore tomcat -/opt/tomcat/bin/shutdown.sh -rm -rf /opt/tomcat/webapps/idm* -rm -rf /opt/tomcat/temp/* /opt/tomcat/work/* /opt/tomcat/logs/* - - -#shutdown and restore LDAP -/opt/ldap1/OpenDJ-2.4.4/bin/stop-ds -/opt/ldap2/OpenDJ-2.4.4/bin/stop-ds -rm -rf /opt/ldap1/ -rm -rf /opt/ldap2/ - -(cd /opt; unzip ldaps.zip) -/opt/ldap1/OpenDJ-2.4.4/bin/start-ds | grep "started successfully" -/opt/ldap2/OpenDJ-2.4.4/bin/start-ds | grep "started successfully" -/opt/ldap1/OpenDJ-2.4.4/bin/dsreplication status --baseDN "dc=systest,dc=com" \ - --adminUID admin --adminPassword password -X -n | grep -v "\[.\]" - -#remove midpoint home -rm -rf /opt/midpoint/* diff --git a/testing/systest/src/test/scripts/systest-env-shutdown.sh b/testing/systest/src/test/scripts/systest-env-shutdown.sh deleted file mode 100755 index 2cf4183e122..00000000000 --- a/testing/systest/src/test/scripts/systest-env-shutdown.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# shutdown tomcat -/opt/tomcat/bin/shutdown.sh - -#shutdown LDAP -/opt/ldap1/OpenDJ-2.4.4/bin/stop-ds -/opt/ldap2/OpenDJ-2.4.4/bin/stop-ds diff --git a/testing/systest/testng-integration.xml b/testing/systest/testng-integration.xml deleted file mode 100644 index 969d587dca5..00000000000 --- a/testing/systest/testng-integration.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - diff --git a/testing/systest/testng-unit.xml b/testing/systest/testng-unit.xml deleted file mode 100644 index 0dfa9d858ca..00000000000 --- a/testing/systest/testng-unit.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - From 63dcdf64d93b3f41f8c4fdd9120116d4686a591a Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Fri, 4 Dec 2015 16:06:18 +0100 Subject: [PATCH 065/116] Refactoring TestDummy --- .../provisioning/test/impl/TestDummy.java | 83 +++++++++---------- .../midpoint/test/IntegrationTestTools.java | 9 ++ 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java index 30022bbb046..5983f0fe99b 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java @@ -243,10 +243,10 @@ public void test000Integrity() throws ObjectNotFoundException, SchemaException { display("getObject result", result); TestUtil.assertSuccess(result); - - // Check connector schema ProvisioningTestUtil.assertConnectorSchemaSanity(connector, prismContext); + + IntegrationTestTools.assertNoSchema(resource); } /** @@ -257,11 +257,11 @@ public void test000Integrity() throws ObjectNotFoundException, SchemaException { * */ @Test - public void test001Connectors() throws SchemaException { - TestUtil.displayTestTile("test001Connectors"); + public void test010Connectors() throws Exception { + final String TEST_NAME = "test010Connectors"; + TestUtil.displayTestTile(TEST_NAME); // GIVEN - OperationResult result = new OperationResult(TestDummy.class.getName() - + ".test001Connectors"); + OperationResult result = new OperationResult(TestDummy.class.getName() + "." + TEST_NAME); // WHEN List> connectors = repositoryService.searchObjects(ConnectorType.class, @@ -308,11 +308,11 @@ public void test001Connectors() throws SchemaException { * new was installed in the meantime. */ @Test - public void test002ConnectorRediscovery() { - TestUtil.displayTestTile("test002ConnectorRediscovery"); + public void test012ConnectorRediscovery() { + final String TEST_NAME = "test012ConnectorRediscovery"; + TestUtil.displayTestTile(TEST_NAME); // GIVEN - OperationResult result = new OperationResult(TestDummy.class.getName() - + ".test002ConnectorRediscovery"); + OperationResult result = new OperationResult(TestDummy.class.getName() + "." + TEST_NAME); // WHEN Set discoverLocalConnectors = connectorManager.discoverLocalConnectors(result); @@ -332,11 +332,11 @@ public void test002ConnectorRediscovery() { * that executes testResource and checks whether the schema was generated. */ @Test - public void test003Connection() throws ObjectNotFoundException, SchemaException { - TestUtil.displayTestTile("test003Connection"); + public void test020Connection() throws Exception { + final String TEST_NAME = "test020Connection"; + TestUtil.displayTestTile(TEST_NAME); // GIVEN - OperationResult result = new OperationResult(TestDummy.class.getName() - + ".test003Connection"); + OperationResult result = new OperationResult(TestDummy.class.getName() + "." + TEST_NAME); // Some connector initialization and other things might happen in previous tests. // The monitor is static, not part of spring context, it will not be cleared @@ -356,9 +356,7 @@ public void test003Connection() throws ObjectNotFoundException, SchemaException ConnectorType connector = repositoryService.getObject(ConnectorType.class, resourceTypeBefore.getConnectorRef().getOid(), null, result).asObjectable(); assertNotNull(connector); - XmlSchemaType xmlSchemaTypeBefore = resourceTypeBefore.getSchema(); - Element resourceXsdSchemaElementBefore = ResourceTypeUtil.getResourceXsdSchema(resourceTypeBefore); - AssertJUnit.assertNull("Found schema before test connection. Bad test setup?", resourceXsdSchemaElementBefore); + IntegrationTestTools.assertNoSchema("Found schema before test connection. Bad test setup?", resourceTypeBefore); // WHEN OperationResult testResult = provisioningService.testResource(RESOURCE_DUMMY_OID); @@ -402,12 +400,11 @@ public void test003Connection() throws ObjectNotFoundException, SchemaException } @Test - public void test004Configuration() throws ObjectNotFoundException, CommunicationException, SchemaException, - ConfigurationException, SecurityViolationException { - TestUtil.displayTestTile("test004Configuration"); + public void test021Configuration() throws Exception { + final String TEST_NAME = "test021Configuration"; + TestUtil.displayTestTile(TEST_NAME); // GIVEN - OperationResult result = new OperationResult(TestDummy.class.getName() - + ".test004Configuration"); + OperationResult result = new OperationResult(TestDummy.class.getName() + "." + TEST_NAME); // WHEN resource = provisioningService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, null, result); @@ -453,9 +450,9 @@ public void test004Configuration() throws ObjectNotFoundException, Communication } @Test - public void test005ParsedSchema() throws ObjectNotFoundException, CommunicationException, SchemaException, - ConfigurationException { - TestUtil.displayTestTile("test005ParsedSchema"); + public void test022ParsedSchema() throws Exception { + final String TEST_NAME = "test022ParsedSchema"; + TestUtil.displayTestTile(TEST_NAME); // GIVEN // THEN @@ -481,8 +478,8 @@ public void test005ParsedSchema() throws ObjectNotFoundException, CommunicationE } @Test - public void test006RefinedSchema() throws Exception { - final String TEST_NAME = "test006RefinedSchema"; + public void test023RefinedSchema() throws Exception { + final String TEST_NAME = "test023RefinedSchema"; TestUtil.displayTestTile(TEST_NAME); // GIVEN @@ -546,8 +543,8 @@ public void test006RefinedSchema() throws Exception { } @Test - public void test007Capabilities() throws Exception { - final String TEST_NAME = "test007Capabilities"; + public void test024Capabilities() throws Exception { + final String TEST_NAME = "test024Capabilities"; TestUtil.displayTestTile(TEST_NAME); // GIVEN @@ -619,8 +616,8 @@ public void test007Capabilities() throws Exception { * Check if the cached native capabilities were properly stored in the repo */ @Test - public void test008CapabilitiesRepo() throws Exception { - final String TEST_NAME = "test008CapabilitiesRepo"; + public void test025CapabilitiesRepo() throws Exception { + final String TEST_NAME = "test025CapabilitiesRepo"; TestUtil.displayTestTile(TEST_NAME); // GIVEN @@ -680,8 +677,8 @@ public void test008CapabilitiesRepo() throws Exception { } @Test - public void test010ResourceAndConnectorCaching() throws Exception { - TestUtil.displayTestTile("test010ResourceAndConnectorCaching"); + public void test030ResourceAndConnectorCaching() throws Exception { + TestUtil.displayTestTile("test030ResourceAndConnectorCaching"); // GIVEN OperationResult result = new OperationResult(TestOpenDJ.class.getName() @@ -760,8 +757,8 @@ public void test010ResourceAndConnectorCaching() throws Exception { } @Test - public void test011ResourceAndConnectorCachingForceFresh() throws Exception { - TestUtil.displayTestTile("test011ResourceAndConnectorCachingForceFresh"); + public void test031ResourceAndConnectorCachingForceFresh() throws Exception { + TestUtil.displayTestTile("test031ResourceAndConnectorCachingForceFresh"); // GIVEN OperationResult result = new OperationResult(TestDummy.class.getName() @@ -817,8 +814,8 @@ public void test011ResourceAndConnectorCachingForceFresh() throws Exception { @Test - public void test020ApplyDefinitionShadow() throws Exception { - final String TEST_NAME = "test020ApplyDefinitionShadow"; + public void test040ApplyDefinitionShadow() throws Exception { + final String TEST_NAME = "test040ApplyDefinitionShadow"; TestUtil.displayTestTile(TEST_NAME); // GIVEN @@ -843,8 +840,8 @@ public void test020ApplyDefinitionShadow() throws Exception { } @Test - public void test021ApplyDefinitionAddShadowDelta() throws Exception { - final String TEST_NAME = "test021ApplyDefinitionAddShadowDelta"; + public void test041ApplyDefinitionAddShadowDelta() throws Exception { + final String TEST_NAME = "test041ApplyDefinitionAddShadowDelta"; TestUtil.displayTestTile(TEST_NAME); // GIVEN @@ -870,8 +867,8 @@ public void test021ApplyDefinitionAddShadowDelta() throws Exception { } @Test - public void test022ApplyDefinitionResource() throws Exception { - final String TEST_NAME = "test022ApplyDefinitionResource"; + public void test042ApplyDefinitionResource() throws Exception { + final String TEST_NAME = "test042ApplyDefinitionResource"; TestUtil.displayTestTile(TEST_NAME); // GIVEN @@ -900,8 +897,8 @@ public void test022ApplyDefinitionResource() throws Exception { } @Test - public void test023ApplyDefinitionAddResourceDelta() throws Exception { - final String TEST_NAME = "test023ApplyDefinitionAddResourceDelta"; + public void test043ApplyDefinitionAddResourceDelta() throws Exception { + final String TEST_NAME = "test043ApplyDefinitionAddResourceDelta"; TestUtil.displayTestTile(TEST_NAME); // GIVEN diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java index 558f909da6a..425db40e2fa 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java @@ -927,4 +927,13 @@ public static void assertNoAssociation(PrismObject shadow, QName ass } } } + + public static void assertNoSchema(ResourceType resourceType) { + assertNoSchema("Found schema in resource "+resourceType+" while not expecting it", resourceType); + } + + public static void assertNoSchema(String message, ResourceType resourceType) { + Element resourceXsdSchema = ResourceTypeUtil.getResourceXsdSchema(resourceType); + AssertJUnit.assertNull(message, resourceXsdSchema); + } } From 0aec560421a63db1d46f0d0d7f3e8cbe14e18527 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Fri, 4 Dec 2015 21:38:51 +0100 Subject: [PATCH 066/116] Support for noFetch for ResourceType (provisioning) (MID-2707) --- .../schema/result/OperationResult.java | 2 +- .../impl/ProvisioningContext.java | 2 +- .../impl/ProvisioningServiceImpl.java | 22 +++--- .../provisioning/impl/ResourceManager.java | 71 +++++++------------ .../provisioning/impl/ShadowCache.java | 4 +- .../provisioning/test/impl/TestDummy.java | 51 +++++++++++-- 6 files changed, 85 insertions(+), 67 deletions(-) diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java index fbf2741823a..4b09232fad7 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java @@ -1271,7 +1271,7 @@ public void cleanupResult(Throwable e) { OperationResult subresult = iterator.next(); if (subresult.getStatus() == OperationResultStatus.UNKNOWN) { String message = "Subresult "+subresult.getOperation()+" of operation "+operation+" is still UNKNOWN during cleanup"; - LOGGER.error("{}:\n{}", message, this.debugDump()); + LOGGER.error("{}:\n{}", message, this.debugDump(), e); if (e == null) { throw new IllegalStateException(message); } else { diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java index 0a2ee2515af..6c08d2cef25 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java @@ -106,7 +106,7 @@ public ResourceType getResource() throws ObjectNotFoundException, SchemaExceptio if (resourceOid == null) { throw new SchemaException("Null resource OID "+getDesc()); } - resource = resourceManager.getResource(resourceOid, parentResult).asObjectable(); + resource = resourceManager.getResource(resourceOid, null, parentResult).asObjectable(); if (resource != null && resource.getName() != null) { super.setResourceName(resource.getName().getOrig()); } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java index 3cc26f98332..c1aff4eeb27 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java @@ -201,7 +201,7 @@ public PrismObject getObject(Class type, String oid // (fresh) // schema try { - resultingObject = (PrismObject) resourceManager.getResource(oid, result); + resultingObject = (PrismObject) resourceManager.getResource(oid, SelectorOptions.findRootOptions(options), result); } catch (ObjectNotFoundException ex) { ProvisioningUtil.recordFatalError(LOGGER, result, "Resource object not found", ex); throw ex; @@ -497,7 +497,7 @@ public SearchResultList> searchObjects(Cla SearchResultMetadata metadata; try { if (!ShadowType.class.isAssignableFrom(type)) { - SearchResultList> objects = searchRepoObjects(type, query, result); + SearchResultList> objects = searchRepoObjects(type, query, options, result); result.computeStatus(); result.recordSuccessIfUnknown(); result.cleanupResult(); @@ -543,7 +543,8 @@ public boolean handle(PrismObject object, OperationResult parentResult) { @SuppressWarnings("unchecked") - private SearchResultList> searchRepoObjects(Class type, ObjectQuery query, OperationResult result) throws SchemaException { + private SearchResultList> searchRepoObjects(Class type, ObjectQuery query, + Collection> options, OperationResult result) throws SchemaException { List> repoObjects = null; @@ -558,7 +559,7 @@ private SearchResultList> searchRepoObject try { - PrismObject completeResource = completeObject(type, repoObject, objResult); + PrismObject completeResource = completeObject(type, repoObject, options, objResult); newObjListType.add((PrismObject) completeResource); objResult.computeStatusIfUnknown(); @@ -626,12 +627,13 @@ private SearchResultList> searchRepoObject } - private PrismObject completeObject(Class type, PrismObject inObject, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { + private PrismObject completeObject(Class type, PrismObject inObject, + Collection> options, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { if (ResourceType.class.equals(type)) { - PrismObject completeResource = resourceManager.getResource((PrismObject) inObject, - result); + PrismObject completeResource = resourceManager.getResource((PrismObject) inObject, + SelectorOptions.findRootOptions(options), result); return (PrismObject) completeResource; } else { @@ -1026,7 +1028,7 @@ public void finishOperation(PrismObject object, Provis @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public SearchResultMetadata searchObjectsIterative(final Class type, ObjectQuery query, - Collection> options, + final Collection> options, final ResultHandler handler, Task task, final OperationResult parentResult) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException { @@ -1072,7 +1074,7 @@ public SearchResultMetadata searchObjectsIterative(final public boolean handle(PrismObject object, OperationResult objResult) { PrismObject completeObject; try { - completeObject = completeObject(type, object, objResult); + completeObject = completeObject(type, object, options, objResult); } catch (SchemaException e) { LOGGER.error("Error while completing {}: {}. Using non-complete object.", new Object[] { object, e.getMessage(), e }); @@ -1270,7 +1272,7 @@ public void applyDefinition(ObjectDelta delta, Objecta if (ShadowType.class.isAssignableFrom(delta.getObjectTypeClass())){ getShadowCache(Mode.STANDARD).applyDefinition((ObjectDelta) delta, (ShadowType) object, result); } else if (ResourceType.class.isAssignableFrom(delta.getObjectTypeClass())){ - resourceManager.applyDefinition((ObjectDelta) delta, (ResourceType) object, result); + resourceManager.applyDefinition((ObjectDelta) delta, (ResourceType) object, null, result); } else { throw new IllegalArgumentException("Could not apply definition to deltas for object type: " + delta.getObjectTypeClass()); } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java index 2da4e681666..10d057cb7b0 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java @@ -64,6 +64,8 @@ import com.evolveum.midpoint.provisioning.util.ProvisioningUtil; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.CapabilityUtil; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.ConnectorTestOperation; import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttributeContainerDefinition; @@ -115,7 +117,7 @@ public class ResourceManager { private static final String OPERATION_COMPLETE_RESOURCE = ResourceManager.class.getName() + ".completeResource"; - public PrismObject getResource(PrismObject repositoryObject, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException{ + public PrismObject getResource(PrismObject repositoryObject, GetOperationOptions options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException{ InternalMonitor.getResourceCacheStats().recordRequest(); PrismObject cachedResource = resourceCache.get(repositoryObject); @@ -127,10 +129,10 @@ public PrismObject getResource(PrismObject repositor LOGGER.debug("Storing fetched resource {}, version {} to cache (previously cached version {})", new Object[]{ repositoryObject.getOid(), repositoryObject.getVersion(), resourceCache.getVersion(repositoryObject.getOid())}); - return putToCache(repositoryObject, parentResult); + return loadAndCacheResource(repositoryObject, options, parentResult); } - public PrismObject getResource(String oid, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException{ + public PrismObject getResource(String oid, GetOperationOptions options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException{ InternalMonitor.getResourceCacheStats().recordRequest(); String version = repositoryService.getVersion(ResourceType.class, oid, parentResult); @@ -150,13 +152,19 @@ public PrismObject getResource(String oid, OperationResult parentR PrismObject repositoryObject = repositoryService.getObject(ResourceType.class, oid, null, parentResult); - return putToCache(repositoryObject, parentResult); + return loadAndCacheResource(repositoryObject, options, parentResult); } - private PrismObject putToCache(PrismObject repositoryObject, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + private PrismObject loadAndCacheResource(PrismObject repositoryObject, + GetOperationOptions options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - PrismObject completedResource = completeResource(repositoryObject, null, false, parentResult); + PrismObject completedResource = completeResource(repositoryObject, null, false, options, parentResult); + + if (!isComplete(completedResource)) { + // No not cache non-complete resources (e.g. those retrieved with noFetch) + return completedResource; + } if (LOGGER.isTraceEnabled()) { LOGGER.trace("Putting resource in cache:\n{}", completedResource.debugDump()); @@ -215,7 +223,7 @@ public void deleteResource(String oid, ProvisioningOperationOptions options, Tas * @throws ConfigurationException */ private PrismObject completeResource(PrismObject repoResource, ResourceSchema resourceSchema, - boolean fetchedSchema, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, + boolean fetchedSchema, GetOperationOptions options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { // do not add as a subresult..it will be added later, if the completing @@ -252,6 +260,12 @@ private PrismObject completeResource(PrismObject rep } else { // The resource is NOT complete. Try to fetch schema and capabilities + + if (GetOperationOptions.isNoFetch(options)) { + // We need to fetch schema, but the noFetch option is specified. Therefore return whatever we have. + result.recordSuccessIfUnknown(); + return repoResource; + } ConnectorInstance connector = null; try { @@ -661,7 +675,7 @@ public void testConnection(PrismObject resource, OperationResult p // generate the resource schema - until we have full schema caching // capability. try { - resource = completeResource(resource, schema, true, schemaResult); + resource = completeResource(resource, schema, true, null, schemaResult); } catch (ObjectNotFoundException e) { schemaResult.recordFatalError( "Object not found (unexpected error, probably a bug): " + e.getMessage(), e); @@ -770,41 +784,6 @@ private void adjustSchemaForSimulatedCapabilities(PrismObject reso } } - public ResourceSchema getResourceSchema(ResourceType resource, OperationResult parentResult) throws SchemaException, CommunicationException, - ConfigurationException { - - ResourceSchema schema = null; - try { - - if (!isComplete(resource.asPrismObject())) { - // Make sure that the schema is retrieved from the resource - // this will also retrieve the schema from cache and/or parse it if - // needed - resource = completeResource(resource.asPrismObject(), null, false, parentResult).asObjectable(); - } - schema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - - } catch (SchemaException e) { - parentResult.recordFatalError("Unable to parse resource schema: " + e.getMessage(), e); - throw new SchemaException("Unable to parse resource schema: " + e.getMessage(), e); - } catch (ObjectNotFoundException e) { - // this really should not happen - parentResult.recordFatalError("Unexpected ObjectNotFoundException: " + e.getMessage(), e); - throw new SystemException("Unexpected ObjectNotFoundException: " + e.getMessage(), e); - } catch (ConfigurationException e) { - parentResult.recordFatalError("Unable to parse resource schema: " + e.getMessage(), e); - throw new ConfigurationException("Unable to parse resource schema: " + e.getMessage(), e); - } - - if (schema == null) { - return null; - } - - checkSchema(schema); - - return schema; - } - private void checkSchema(PrismSchema schema) throws SchemaException { // This is resource schema, it should contain only // ResourceObjectDefintions @@ -834,7 +813,7 @@ private ConnectorInstance getConnectorInstance(PrismObject resourc return connectorTypeManager.getConfiguredConnectorInstance(resource, forceFresh, parentResult); } - public void applyDefinition(ObjectDelta delta, ResourceType resourceWhenNoOid, OperationResult objectResult) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { + public void applyDefinition(ObjectDelta delta, ResourceType resourceWhenNoOid, GetOperationOptions options, OperationResult objectResult) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { if (delta.isAdd()) { PrismObject resource = delta.getObjectToAdd(); @@ -859,7 +838,7 @@ public void applyDefinition(ObjectDelta delta, ResourceType resour Validate.notNull(resourceWhenNoOid, "Resource oid not specified in the object delta, and resource is not specified as well. Could not apply definition."); resource = resourceWhenNoOid.asPrismObject(); } else { - resource = getResource(resourceOid, objectResult); + resource = getResource(resourceOid, options, objectResult); } ResourceType resourceType = resource.asObjectable(); @@ -979,7 +958,7 @@ public void applyDefinition(ObjectQuery query, OperationResult result) { } public Object executeScript(String resourceOid, ProvisioningScriptType script, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { - PrismObject resource = getResource(resourceOid, result); + PrismObject resource = getResource(resourceOid, null, result); ConnectorInstance connectorInstance = connectorTypeManager.getConfiguredConnectorInstance(resource, false, result); ExecuteProvisioningScriptOperation scriptOperation = ProvisioningUtil.convertToScriptOperation(script, "script on "+resource, prismContext); try { diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java index b51bcbe16d8..7a966f6c12c 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java @@ -639,8 +639,6 @@ public void visit(ObjectFilter filter) { throw e; } } - - protected ResourceType getResource(ResourceShadowDiscriminator coords, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { @@ -648,7 +646,7 @@ protected ResourceType getResource(ResourceShadowDiscriminator coords, Operation if (resourceOid == null) { throw new IllegalArgumentException("No resource OID in " + coords); } - return resourceManager.getResource(resourceOid, parentResult).asObjectable(); + return resourceManager.getResource(resourceOid, null, parentResult).asObjectable(); } @SuppressWarnings("rawtypes") diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java index 5983f0fe99b..6831dfe13a0 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/test/impl/TestDummy.java @@ -252,13 +252,10 @@ public void test000Integrity() throws ObjectNotFoundException, SchemaException { /** * Check whether the connectors were discovered correctly and were added to * the repository. - * - * @throws SchemaException - * */ @Test - public void test010Connectors() throws Exception { - final String TEST_NAME = "test010Connectors"; + public void test010ListConnectors() throws Exception { + final String TEST_NAME = "test010ListConnectors"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestDummy.class.getName() + "." + TEST_NAME); @@ -324,6 +321,48 @@ public void test012ConnectorRediscovery() { assertTrue("Rediscovered something", discoverLocalConnectors.isEmpty()); } + /** + * List resources with noFetch option. This is what GUI does. This operation + * should be harmless and should not change resource state. + */ + @Test + public void test015ListResourcesNoFetch() throws Exception { + final String TEST_NAME = "test015ListResourcesNoFetch"; + TestUtil.displayTestTile(TEST_NAME); + // GIVEN + Task task = taskManager.createTaskInstance(TestDummy.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + Collection> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch()); + + // WHEN + SearchResultList> resources = provisioningService.searchObjects(ResourceType.class, null, options, task, result); + + // THEN + result.computeStatus(); + display("searchObjects result", result); + TestUtil.assertSuccess(result); + + assertFalse("No resources found", resources.isEmpty()); + for (PrismObject resource : resources) { + ResourceType resourceType = resource.asObjectable(); + display("Found resource " + resourceType, resourceType); + + display("XML " + resourceType, PrismTestUtil.serializeObjectToString(resource, PrismContext.LANG_XML)); + + XmlSchemaType xmlSchemaType = resourceType.getSchema(); + if (xmlSchemaType != null) { + Element xsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(resourceType); + assertNull("Found schema in "+resource, xsdSchemaElement); + } + } + + assertConnectorSchemaParseIncrement(1); + assertConnectorCapabilitiesFetchIncrement(0); + assertConnectorInitializationCountIncrement(0); + assertResourceSchemaFetchIncrement(0); + assertResourceSchemaParseCountIncrement(0); + } + /** * This should be the very first test that works with the resource. * @@ -390,7 +429,7 @@ public void test020Connection() throws Exception { // schema will be checked in next test assertResourceSchemaFetchIncrement(1); - assertConnectorSchemaParseIncrement(1); + assertConnectorSchemaParseIncrement(0); assertConnectorCapabilitiesFetchIncrement(1); assertConnectorInitializationCountIncrement(1); assertResourceSchemaParseCountIncrement(1); From 0d5f944377b0041348bcb0b718da75c6596ee339 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 4 Dec 2015 23:26:41 +0100 Subject: [PATCH 067/116] QI2: Eliminating redundant joins for singletons. --- .../repo/sql/QueryInterpreter2Test.java | 44 ++++++++++++++++--- .../repo/sql/query2/hqm/EntityReference.java | 9 ++++ .../query2/hqm/condition/AndCondition.java | 2 + .../sql/query2/hqm/condition/InCondition.java | 21 +++++++++ .../hqm/condition/IsNotNullCondition.java | 2 + .../query2/hqm/condition/IsNullCondition.java | 2 + .../hqm/condition/JunctionCondition.java | 16 +++++++ .../query2/hqm/condition/NotCondition.java | 16 +++++++ .../sql/query2/hqm/condition/OrCondition.java | 1 + .../hqm/condition/PropertyCondition.java | 16 +++++++ .../PropertyPropertyComparisonCondition.java | 23 ++++++++++ .../condition/SimpleComparisonCondition.java | 23 ++++++++++ .../query2/resolution/ItemPathResolver.java | 43 ++++++++++++++++-- 13 files changed, 208 insertions(+), 10 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index cd1f8410d18..97b190ffd8a 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -118,6 +118,7 @@ import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_RESPONSE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_STAGE_NUMBER; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_EXTENSION; import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_NAME; /** @@ -566,6 +567,40 @@ public void test070QueryGenericLong() throws Exception { } } + @Test + public void test071QueryGenericLongTwice() throws Exception { + Session session = open(); + try { + ObjectQuery query = QueryBuilder.queryFor(GenericObjectType.class, prismContext) + .item(F_NAME).eqPoly("generic object", "generic object").matchingNorm() + .and().item(F_EXTENSION, new QName("intType")).ge(100) + .and().item(F_EXTENSION, new QName("intType")).lt(200) + .and().item(F_EXTENSION, new QName("longType")).eq(335) + .build(); + + String real = getInterpretedQuery2(session, GenericObjectType.class, query); + + String expected = "select\n" + + " g.fullObject, g.stringsCount, g.longsCount, g.datesCount, g.referencesCount, g.polysCount, g.booleansCount\n" + + "from\n" + + " RGenericObject g\n" + + " left join g.longs l with ( l.ownerType = :ownerType and l.name = :name )\n" + + " left join g.longs l2 with ( l2.ownerType = :ownerType2 and l2.name = :name2 )\n" + + "where\n" + + " (\n" + + " g.name.norm = :norm and\n" + + " l.value >= :value and\n" + + " l.value < :value2 and\n" + + " l2.value = :value3\n" + + " )"; + + // note l and l2 cannot be merged as they point to different extension properties (intType, longType) + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test072QueryAccountByAttribute() throws Exception { Session session = open(); @@ -2583,16 +2618,12 @@ public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Excep .build(); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); - // TODO TODO TODO - // when referencing singleton more times (like a.owner here) we should do only 1 join - String expected = "select\n" + " a.fullObject\n" + "from\n" + " RAccessCertificationCase a\n" + " left join a.reviewerRef r\n" + " left join a.owner o\n" + - " left join a.owner o2\n" + "where\n" + " (\n" + " (\n" + @@ -2607,7 +2638,7 @@ public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Excep " o.stageNumber is null\n" + " )\n" + " ) and\n" + - " o2.state = :state\n" + + " o.state = :state\n" + " )\n" + "order by a.reviewRequestedTimestamp desc"; assertEqualsIgnoreWhitespace(expected, real); @@ -3037,7 +3068,6 @@ public void test925DecisionsNotAnsweredOrderBy() throws Exception { " RAccessCertificationCase a\n" + " left join a.decision d\n" + " left join a.owner o\n" + - " left join a.owner o2\n" + "where\n" + " (\n" + " (\n" + @@ -3056,7 +3086,7 @@ public void test925DecisionsNotAnsweredOrderBy() throws Exception { " d.response = :response\n" + " )\n" + " )\n" + - "order by o.name.orig asc, a.id asc, o2.oid asc\n"; + "order by o.name.orig asc, a.id asc, o.oid asc\n"; assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java index 2a811887e1c..dd172238edb 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/EntityReference.java @@ -95,4 +95,13 @@ public boolean containsAlias(String alias) { } return false; } + + public JoinSpecification findJoinFor(String path) { + for (JoinSpecification join : joins) { + if (path.equals(join.getPath())) { + return join; + } + } + return null; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java index 5674a014de5..a9e90fa5cd7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/AndCondition.java @@ -37,4 +37,6 @@ public AndCondition(RootHibernateQuery rootHibernateQuery, Collection public void dumpToHql(StringBuilder sb, int indent) { super.dumpToHql(sb, indent, "and"); } + + // inherited "equals" is OK } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java index 925ec83b916..708184ced67 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/InCondition.java @@ -55,4 +55,25 @@ public void dumpToHql(StringBuilder sb, int indent) { sb.append(propertyPath).append(" in (").append(innerQueryText).append(")"); } } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + InCondition that = (InCondition) o; + + if (values != null ? !values.equals(that.values) : that.values != null) return false; + return !(innerQueryText != null ? !innerQueryText.equals(that.innerQueryText) : that.innerQueryText != null); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (values != null ? values.hashCode() : 0); + result = 31 * result + (innerQueryText != null ? innerQueryText.hashCode() : 0); + return result; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java index 0301fc1d3f7..97236e1bfd2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNotNullCondition.java @@ -33,4 +33,6 @@ public void dumpToHql(StringBuilder sb, int indent) { HibernateQuery.indent(sb, indent); sb.append(propertyPath).append(" is not null"); } + + // inherited "equals" is OK } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java index 2f8ccf687f0..9fea6a8cd3b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/IsNullCondition.java @@ -33,4 +33,6 @@ public void dumpToHql(StringBuilder sb, int indent) { HibernateQuery.indent(sb, indent); sb.append(propertyPath).append(" is null"); } + + // inherited "equals" is OK } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java index 812c492a628..5c472a22275 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/JunctionCondition.java @@ -69,4 +69,20 @@ public void dumpToHql(StringBuilder sb, int indent, String logicalOperation) { sb.append(")"); } } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JunctionCondition that = (JunctionCondition) o; + + return components.equals(that.components); + + } + + @Override + public int hashCode() { + return components.hashCode(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java index e76e4fa79f9..d633739c0e9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/NotCondition.java @@ -39,4 +39,20 @@ public void dumpToHql(StringBuilder sb, int indent) { sb.append("not "); child.dumpToHql(sb, -1); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + NotCondition that = (NotCondition) o; + + return child.equals(that.child); + + } + + @Override + public int hashCode() { + return child.hashCode(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java index a80cda7b832..79e1af1fc92 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/OrCondition.java @@ -32,4 +32,5 @@ public void dumpToHql(StringBuilder sb, int indent) { super.dumpToHql(sb, indent, "or"); } + // inherited "equals" is OK } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java index a1fd2d37d30..cc933ac6cc3 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyCondition.java @@ -50,4 +50,20 @@ protected String createParameterName(String propertyPath) { } } } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PropertyCondition that = (PropertyCondition) o; + + return propertyPath.equals(that.propertyPath); + + } + + @Override + public int hashCode() { + return propertyPath.hashCode(); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java index 4c4f34c8dc7..2d74c9036f7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/PropertyPropertyComparisonCondition.java @@ -54,4 +54,27 @@ public void dumpToHql(StringBuilder sb, int indent) { sb.append(finalPropertyPath).append(" ").append(operator).append(" ").append(finalRightSidePropertyPath); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + PropertyPropertyComparisonCondition that = (PropertyPropertyComparisonCondition) o; + + if (ignoreCase != that.ignoreCase) return false; + if (!rightSidePath.equals(that.rightSidePath)) return false; + return operator.equals(that.operator); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + rightSidePath.hashCode(); + result = 31 * result + operator.hashCode(); + result = 31 * result + (ignoreCase ? 1 : 0); + return result; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java index 71ef0ac39f0..9786436f388 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/condition/SimpleComparisonCondition.java @@ -60,4 +60,27 @@ public void dumpToHql(StringBuilder sb, int indent) { String parameterName = rootHibernateQuery.addParameter(parameterNamePrefix, finalPropertyValue); sb.append(finalPropertyPath).append(" ").append(operator).append(" :").append(parameterName); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + SimpleComparisonCondition that = (SimpleComparisonCondition) o; + + if (ignoreCase != that.ignoreCase) return false; + if (value != null ? !value.equals(that.value) : that.value != null) return false; + return operator.equals(that.operator); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (value != null ? value.hashCode() : 0); + result = 31 * result + operator.hashCode(); + result = 31 * result + (ignoreCase ? 1 : 0); + return result; + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java index 1af14028f4e..aceaec90341 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/resolution/ItemPathResolver.java @@ -35,6 +35,7 @@ import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.lang.ObjectUtils; import javax.xml.namespace.QName; import java.lang.reflect.InvocationTargetException; @@ -90,7 +91,44 @@ String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) th RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String joinedItemJpaName = joinedItemDefinition.getJpaName(); String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName; - String joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); + String joinedItemAlias; + if (!joinedItemDefinition.isMultivalued()) { + /* + * Let's check if we were already here i.e. if we had already created this join. + * This is to avoid useless creation of redundant joins for singleton items. + * + * But how can we be sure that item is singleton if we look only at the last segment (which is single-valued)? + * Imagine we are creating join for single-valued entity of u.abc.(...).xyz.ent where + * ent is single-valued and not embedded (so we are to create something like "left join u.abc.(...).xyz.ent e"). + * Then "u" is certainly a single value: either the root object, or some value pointed to by Exists restriction. + * Also, abc, ..., xyz are surely single-valued: otherwise they would be connected by a join. So, + * u.abc.(...).xyz.ent is a singleton. + * + * Look at it in other way: if e.g. xyz was multivalued, then we would have something like: + * left join u.abc.(...).uvw.xyz x + * left join x.ent e + * And, therefore we would not be looking for u.abc.(...).xyz.ent. + */ + + JoinSpecification existingJoin = hibernateQuery.getPrimaryEntity().findJoinFor(joinedItemFullPath); + if (existingJoin != null) { + // but let's check the condition as well + String existingAlias = existingJoin.getAlias(); + // we have to create condition for existing alias, to be matched to existing condition + Condition conditionForExistingAlias = createJoinCondition(existingAlias, joinedItemDefinition, hibernateQuery); + if (ObjectUtils.equals(conditionForExistingAlias, existingJoin.getCondition())) { + LOGGER.trace("Reusing alias '{}' for joined path '{}'", existingAlias, joinedItemFullPath); + return existingAlias; + } + } + } + joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition); + Condition condition = createJoinCondition(joinedItemAlias, joinedItemDefinition, hibernateQuery); + hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); + return joinedItemAlias; + } + + private Condition createJoinCondition(String joinedItemAlias, JpaLinkDefinition joinedItemDefinition, RootHibernateQuery hibernateQuery) throws QueryException { Condition condition = null; if (joinedItemDefinition instanceof JpaAnyPropertyLinkDefinition) { JpaAnyPropertyLinkDefinition anyLinkDef = (JpaAnyPropertyLinkDefinition) joinedItemDefinition; @@ -117,8 +155,7 @@ else if (joinedItemDefinition.getCollectionSpecification() instanceof VirtualCol condition = conditions.iterator().next(); } } - hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition)); - return joinedItemAlias; + return condition; } /** From 87a6db5aecd7b8606b7964a7ab90744edb698235 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sat, 5 Dec 2015 00:55:45 +0100 Subject: [PATCH 068/116] QI2: Optimizing parent ID queries - eliminating owner joins. Generalized translation state machine a bit. --- .../midpoint/prism/PrismConstants.java | 8 +- .../midpoint/prism/path/ItemPath.java | 7 + .../repo/sql/QueryInterpreter2Test.java | 138 ++++++++++++++---- .../repo/sql/data/common/RObject.java | 26 +++- .../data/common/any/RAssignmentExtension.java | 3 + .../container/RAccessCertificationCase.java | 3 +- .../data/common/container/RAssignment.java | 39 +++-- .../sql/data/common/container/RExclusion.java | 2 + .../sql/data/common/container/RTrigger.java | 3 +- .../data/common/other/RLookupTableRow.java | 2 + .../repo/sql/query/definition/JaxbPath.java | 39 +++++ .../sql/query/definition/OwnerIdGetter.java | 35 +++++ .../definition/ClassDefinitionParser.java | 36 +++-- .../query2/definition/IdQueryProperty.java | 1 + .../definition/JpaDataNodeDefinition.java | 13 +- .../definition/JpaEntityDefinition.java | 20 ++- .../query2/definition/JpaLinkDefinition.java | 33 ++++- .../definition/LinkDefinitionComparator.java | 8 + 18 files changed, 331 insertions(+), 85 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/JaxbPath.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerIdGetter.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java index 82b27ad3f3b..b5efe79c8d3 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java @@ -28,7 +28,7 @@ public class PrismConstants { public static final String EXTENSION_LOCAL_NAME = "extension"; public static final String NAME_LOCAL_NAME = "name"; - + public static final String ATTRIBUTE_ID_LOCAL_NAME = "id"; public static final String ATTRIBUTE_OID_LOCAL_NAME = "oid"; public static final String ATTRIBUTE_VERSION_LOCAL_NAME = "version"; @@ -93,9 +93,11 @@ public class PrismConstants { public static final QName Q_ANY = new QName(NS_QUERY, "any"); // Path constants - public static final QName T_PARENT = new QName(NS_TYPES, "parent"); + public static final String T_PARENT_LOCAL_PART = "parent"; + public static final QName T_PARENT = new QName(NS_TYPES, T_PARENT_LOCAL_PART); public static final QName T_OBJECT_REFERENCE = new QName(NS_TYPES, "objectReference"); - public static final QName T_ID = new QName(NS_TYPES, "id"); + public static final String T_ID_LOCAL_PART = "id"; + public static final QName T_ID = new QName(NS_TYPES, T_ID_LOCAL_PART); // Misc diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index 0d58f6edcbf..fca5472b763 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -364,6 +364,13 @@ public boolean startsWith(Class clazz) { } } + public boolean startsWith(ItemPath other) { + if (other == null) { + return true; + } + return other.isSubPathOrEquivalent(this); + } + public QName asSingleName() { if (size() == 1 && startsWith(NameItemPathSegment.class)) { return ((NameItemPathSegment) first()).getName(); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 97b190ffd8a..739997e2a97 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -40,11 +40,11 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.prism.query.OrgFilter; -import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; @@ -107,7 +107,8 @@ import static com.evolveum.midpoint.prism.PrismConstants.T_ID; import static com.evolveum.midpoint.prism.PrismConstants.T_PARENT; -import static com.evolveum.midpoint.prism.query.OrderDirection.*; +import static com.evolveum.midpoint.prism.query.OrderDirection.ASCENDING; +import static com.evolveum.midpoint.prism.query.OrderDirection.DESCENDING; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REVIEW_STAGE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_STATE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CURRENT_STAGE_NUMBER; @@ -118,7 +119,13 @@ import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_RESPONSE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_STAGE_NUMBER; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType.F_CONSTRUCTION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType.F_RESOURCE_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType.F_ASSIGNMENT; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType.F_CREATE_APPROVER_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType.F_CREATOR_REF; import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_EXTENSION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_METADATA; import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_NAME; /** @@ -710,14 +717,14 @@ public void test080QueryExistsAssignment() throws Exception { /* * ### UserType: Exists (assignment, Equal (activation/administrativeStatus = Enabled)) */ - ExistsFilter filter = ExistsFilter.createExists(new ItemPath(UserType.F_ASSIGNMENT), UserType.class, prismContext, + ExistsFilter filter = ExistsFilter.createExists(new ItemPath(F_ASSIGNMENT), UserType.class, prismContext, EqualFilter.createEqual(new ItemPath(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), AssignmentType.class, prismContext, null, ActivationStatusType.ENABLED)); ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); query0.setPaging(ObjectPaging.createPaging(F_NAME, ASCENDING)); ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) - .exists(UserType.F_ASSIGNMENT) + .exists(F_ASSIGNMENT) .item(AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS) .eq(ActivationStatusType.ENABLED) .asc(F_NAME) @@ -974,7 +981,7 @@ public void test150QueryUserAssignmentTargetRef() throws Exception { ort.setOid("123"); ort.setType(RoleType.COMPLEX_TYPE); RefFilter filter = RefFilter.createReferenceEqual( - new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_TARGET_REF), + new ItemPath(F_ASSIGNMENT, AssignmentType.F_TARGET_REF), UserType.class, prismContext, ort.asReferenceValue()); String real = getInterpretedQuery2(session, UserType.class, ObjectQuery.createObjectQuery(filter)); String expected = "select\n" + @@ -1042,7 +1049,7 @@ public void test170QueryAssignmentActivationAdministrativeStatus() throws Except try { SchemaRegistry registry = prismContext.getSchemaRegistry(); PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(UserType.class); - ItemPath activationPath = new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); + ItemPath activationPath = new ItemPath(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); ObjectFilter filter = EqualFilter.createEqual(activationPath, objectDef, ActivationStatusType.ENABLED); ObjectQuery query = ObjectQuery.createObjectQuery(filter); String real = getInterpretedQuery2(session, UserType.class, query); @@ -1118,7 +1125,7 @@ public void test182QueryInducementAndAssignmentActivationAdministrativeStatus() PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(RoleType.class); //filter1 - ItemPath activationPath1 = new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); + ItemPath activationPath1 = new ItemPath(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS); ObjectFilter filter1 = EqualFilter.createEqual(activationPath1, objectDef, ActivationStatusType.ENABLED); //filter2 @@ -1421,9 +1428,9 @@ public void test400ActivationQueryWrong() throws Exception { thisScanTimestamp, true), LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM), + LessFilter.createLess(new ItemPath(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO), + LessFilter.createLess(new ItemPath(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true) ); ObjectQuery query0 = ObjectQuery.createObjectQuery(filter); @@ -1431,8 +1438,8 @@ public void test400ActivationQueryWrong() throws Exception { ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext) .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) .or().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) - .or().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) - .or().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .or().item(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .or().item(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) .build(); Session session = open(); @@ -1482,7 +1489,7 @@ public void test405ActivationQueryCorrect() throws Exception { thisScanTimestamp, true), LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true), - ExistsFilter.createExists(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, + ExistsFilter.createExists(new ItemPath(F_ASSIGNMENT), focusObjectDef, OrFilter.createOr( LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), assignmentDef, thisScanTimestamp, true), @@ -1493,7 +1500,7 @@ public void test405ActivationQueryCorrect() throws Exception { ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext) .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) .or().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) - .or().exists(FocusType.F_ASSIGNMENT) + .or().exists(F_ASSIGNMENT) .block() .item(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) .or().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) @@ -1553,15 +1560,15 @@ public void test410ActivationQueryWrong() throws Exception { thisScanTimestamp, true) ), AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + GreaterFilter.createGreater(new ItemPath(F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, lastScanTimestamp, false), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), + LessFilter.createLess(new ItemPath(F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, thisScanTimestamp, true) ), AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + GreaterFilter.createGreater(new ItemPath(F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, lastScanTimestamp, false), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), + LessFilter.createLess(new ItemPath(F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, thisScanTimestamp, true) ) ); @@ -1577,12 +1584,12 @@ public void test410ActivationQueryWrong() throws Exception { .and().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) .endBlock() .or().block() - .item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) - .and().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) + .item(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) + .and().item(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) .endBlock() .or().block() - .item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).gt(lastScanTimestamp) - .and().item(FocusType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) + .item(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).gt(lastScanTimestamp) + .and().item(F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) .endBlock() .build(); @@ -1657,7 +1664,7 @@ public void test415ActivationQueryCorrect() throws Exception { thisScanTimestamp, true) ), AndFilter.createAnd( - ExistsFilter.createExists(new ItemPath(FocusType.F_ASSIGNMENT), focusObjectDef, + ExistsFilter.createExists(new ItemPath(F_ASSIGNMENT), focusObjectDef, OrFilter.createOr( AndFilter.createAnd( GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), @@ -1684,7 +1691,7 @@ public void test415ActivationQueryCorrect() throws Exception { .and().item(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO).le(thisScanTimestamp) .endBlock() .or() - .exists(FocusType.F_ASSIGNMENT) + .exists(F_ASSIGNMENT) .block() .item(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).gt(lastScanTimestamp) .and().item(AssignmentType.F_ACTIVATION, ActivationType.F_VALID_FROM).le(thisScanTimestamp) @@ -2380,11 +2387,11 @@ public void test640queryAssignmentExtensionBoolean() throws Exception { try { SchemaRegistry registry = prismContext.getSchemaRegistry(); PrismObjectDefinition userDef = registry.findObjectDefinitionByCompileTimeClass(UserType.class); - PrismContainerDefinition assignmentDef = userDef.findContainerDefinition(UserType.F_ASSIGNMENT); + PrismContainerDefinition assignmentDef = userDef.findContainerDefinition(F_ASSIGNMENT); PrismPropertyDefinition propDef = assignmentDef.createPropertyDefinition(SKIP_AUTOGENERATION, DOMUtil.XSD_BOOLEAN); EqualFilter eq = EqualFilter.createEqual( - new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_EXTENSION, SKIP_AUTOGENERATION), + new ItemPath(F_ASSIGNMENT, AssignmentType.F_EXTENSION, SKIP_AUTOGENERATION), propDef, null, true); ObjectQuery objectQuery = ObjectQuery.createObjectQuery(eq); @@ -2738,7 +2745,7 @@ public void test760DereferenceAssignedRoleType() throws Exception { */ ObjectFilter filter = EqualFilter.createEqual( - new ItemPath(UserType.F_ASSIGNMENT, AssignmentType.F_TARGET_REF, PrismConstants.T_OBJECT_REFERENCE, RoleType.F_ROLE_TYPE), + new ItemPath(F_ASSIGNMENT, AssignmentType.F_TARGET_REF, PrismConstants.T_OBJECT_REFERENCE, RoleType.F_ROLE_TYPE), UserType.class, prismContext, "type1"); ObjectQuery query = ObjectQuery.createObjectQuery(filter); @@ -3086,7 +3093,84 @@ public void test925DecisionsNotAnsweredOrderBy() throws Exception { " d.response = :response\n" + " )\n" + " )\n" + - "order by o.name.orig asc, a.id asc, o.oid asc\n"; + "order by o.name.orig asc, a.id asc, a.ownerOid asc\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test930ResourceRef() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(F_ASSIGNMENT, F_CONSTRUCTION, F_RESOURCE_REF).ref("1234567") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.assignments a with a.assignmentOwner = :assignmentOwner\n" + + "where\n" + + " (\n" + + " a.resourceRef.targetOid = :targetOid and\n" + + " a.resourceRef.relation = :relation\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test932CreatorRef() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(F_METADATA, F_CREATOR_REF).ref("1234567") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + "where\n" + + " (\n" + + " u.creatorRef.targetOid = :targetOid and\n" + + " u.creatorRef.relation = :relation\n" + + " )\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test934CreateApproverRef() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext) + .item(F_METADATA, F_CREATE_APPROVER_REF).ref("1234567") + .build(); + + String real = getInterpretedQuery2(session, UserType.class, query); + String expected = "select\n" + + " u.fullObject, u.stringsCount, u.longsCount, u.datesCount, u.referencesCount, u.polysCount, u.booleansCount\n" + + "from\n" + + " RUser u\n" + + " left join u.createApproverRef c\n" + + "where\n" + + " (\n" + + " c.targetOid = :targetOid and\n" + + " c.relation = :relation\n" + + " )\n"; assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 9f8ecd02cb2..2b1be53a240 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -36,6 +36,7 @@ import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbPath; import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; @@ -116,15 +117,16 @@ @QueryEntity( anyElements = { @VirtualAny(jaxbNameLocalPart = "extension", ownerType = RObjectExtensionType.EXTENSION) - }, - entities = { - @VirtualEntity( - jaxbName = @JaxbName(localPart = "metadata"), - jaxbType = MetadataType.class, - jpaName = "", - jpaType = Serializable.class // dummy value (ignored) - ) } +// , +// entities = { +// @VirtualEntity( +// jaxbName = @JaxbName(localPart = "metadata"), +// jaxbType = MetadataType.class, +// jpaName = "", +// jpaType = Serializable.class // dummy value (ignored) +// ) +// } ) @Entity @Table(name = "m_object", indexes = { @@ -244,6 +246,7 @@ public byte[] getFullObject() { @OneToMany(mappedBy = RObjectReference.F_OWNER, orphanRemoval = true) // @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @Cascade({org.hibernate.annotations.CascadeType.ALL}) + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "createApproverRef") }) public Set> getCreateApproverRef() { if (createApproverRef == null) { createApproverRef = new HashSet<>(); @@ -251,20 +254,24 @@ public Set> getCreateApproverRef() { return createApproverRef; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "createChannel") }) public String getCreateChannel() { return createChannel; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "createTimestamp") }) public XMLGregorianCalendar getCreateTimestamp() { return createTimestamp; } @Embedded + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "creatorRef") }) public REmbeddedReference getCreatorRef() { return creatorRef; } @Embedded + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifierRef") }) public REmbeddedReference getModifierRef() { return modifierRef; } @@ -273,6 +280,7 @@ public REmbeddedReference getModifierRef() { @OneToMany(mappedBy = RObjectReference.F_OWNER, orphanRemoval = true) // @JoinTable(foreignKey = @ForeignKey(name = "none")) @Cascade({org.hibernate.annotations.CascadeType.ALL}) + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifyApproverRef") }) public Set> getModifyApproverRef() { if (modifyApproverRef == null) { modifyApproverRef = new HashSet<>(); @@ -280,10 +288,12 @@ public Set> getModifyApproverRef() { return modifyApproverRef; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifyChannel") }) public String getModifyChannel() { return modifyChannel; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifyTimestamp") }) public XMLGregorianCalendar getModifyTimestamp() { return modifyTimestamp; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java index 44d5a9ec417..36cb675f027 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAssignmentExtension.java @@ -17,11 +17,14 @@ package com.evolveum.midpoint.repo.sql.data.common.any; import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.container.RAssignment; import com.evolveum.midpoint.repo.sql.data.common.id.RAssignmentExtensionId; import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbPath; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.RUtil; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index e21b371fb9e..36c83ed2f02 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.repo.sql.data.common.other.RCReferenceOwner; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query.definition.OwnerGetter; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; @@ -116,7 +117,7 @@ public RObject getOwner() { } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) - @NotQueryable + @OwnerIdGetter() public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java index 4ec56fd8814..8434e9ac4c5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.repo.sql.data.common.container; +import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.Metadata; import com.evolveum.midpoint.repo.sql.data.common.RObject; @@ -27,7 +28,9 @@ import com.evolveum.midpoint.repo.sql.data.common.type.RAssignmentExtensionType; import com.evolveum.midpoint.repo.sql.data.factory.MetadataFactory; import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbPath; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualEntity; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; @@ -59,18 +62,19 @@ @Entity @QueryEntity( entities = { - @VirtualEntity( - jaxbName = @JaxbName(localPart = "metadata"), - jaxbType = MetadataType.class, - jpaName = "", - jpaType = Serializable.class // dummy value (ignored) - ), - @VirtualEntity( - jaxbName = @JaxbName(localPart = "construction"), - jaxbType = ConstructionType.class, - jpaName = "", - jpaType = Serializable.class // dummy value (ignored) - ) +// @VirtualEntity( +// jaxbName = @JaxbName(localPart = "metadata"), +// jaxbType = MetadataType.class, +// jpaName = "", +// jpaType = Serializable.class // dummy value (ignored) +// ) +// , +// @VirtualEntity( +// jaxbName = @JaxbName(localPart = "construction"), +// jaxbType = ConstructionType.class, +// jpaName = "", +// jpaType = Serializable.class // dummy value (ignored) +// ) } ) @IdClass(RContainerId.class) @@ -138,7 +142,7 @@ public RObject getOwner() { } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) - @NotQueryable + @OwnerIdGetter() public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); @@ -176,6 +180,7 @@ public REmbeddedReference getOrgRef() { } @Embedded + @JaxbPath(itemPath = { @JaxbName(localPart = "construction"), @JaxbName(localPart = "resourceRef") }) public REmbeddedReference getResourceRef() { return resourceRef; } @@ -207,6 +212,7 @@ public Integer getOrder() { @org.hibernate.annotations.ForeignKey(name = "none") @Cascade({org.hibernate.annotations.CascadeType.ALL}) //@JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "createApproverRef") }) public Set getCreateApproverRef() { if (createApproverRef == null) { createApproverRef = new HashSet<>(); @@ -214,20 +220,24 @@ public Set getCreateApproverRef() { return createApproverRef; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "createChannel") }) public String getCreateChannel() { return createChannel; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "createTimestamp") }) public XMLGregorianCalendar getCreateTimestamp() { return createTimestamp; } @Embedded + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "creatorRef") }) public REmbeddedReference getCreatorRef() { return creatorRef; } @Embedded + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifierRef") }) public REmbeddedReference getModifierRef() { return modifierRef; } @@ -236,6 +246,7 @@ public REmbeddedReference getModifierRef() { @OneToMany(mappedBy = RAssignmentReference.F_OWNER, orphanRemoval = true) // @JoinTable(foreignKey = @ForeignKey(name = "none")) @Cascade({org.hibernate.annotations.CascadeType.ALL}) + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifyApproverRef") }) public Set getModifyApproverRef() { if (modifyApproverRef == null) { modifyApproverRef = new HashSet<>(); @@ -243,10 +254,12 @@ public Set getModifyApproverRef() { return modifyApproverRef; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifyChannel") }) public String getModifyChannel() { return modifyChannel; } + @JaxbPath(itemPath = { @JaxbName(localPart = "metadata"), @JaxbName(localPart = "modifyTimestamp") }) public XMLGregorianCalendar getModifyTimestamp() { return modifyTimestamp; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java index 43a206009c3..8b4eadbd45d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RExclusion.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.repo.sql.data.common.enums.RExclusionPolicy; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; @@ -80,6 +81,7 @@ public RObject getOwner() { } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + @OwnerIdGetter() public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java index 39eebb91943..07047cfe147 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RTrigger.java @@ -4,6 +4,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; @@ -60,7 +61,7 @@ public RObject getOwner() { } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) - @NotQueryable + @OwnerIdGetter() public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java index 82fda89553c..0e7f3a19f07 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/other/RLookupTableRow.java @@ -4,6 +4,7 @@ import com.evolveum.midpoint.repo.sql.data.common.container.Container; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; @@ -55,6 +56,7 @@ public RLookupTable getOwner() { } @Column(name = "owner_oid", length = RUtil.COLUMN_LENGTH_OID, nullable = false) + @OwnerIdGetter() public String getOwnerOid() { if (owner != null && ownerOid == null) { ownerOid = owner.getOid(); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/JaxbPath.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/JaxbPath.java new file mode 100644 index 00000000000..face647939a --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/JaxbPath.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query.definition; + +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * @author lazyman + */ +@Target({TYPE, METHOD, FIELD}) +@Retention(RUNTIME) +public @interface JaxbPath { + + JaxbName[] itemPath(); + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerIdGetter.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerIdGetter.java new file mode 100644 index 00000000000..8de959fb816 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/definition/OwnerIdGetter.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.query.definition; + +import com.evolveum.midpoint.repo.sql.data.common.RObject; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Denotes method that is used to access the container parent ID. + * + * @author mederly + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface OwnerIdGetter { + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java index 1b9306329bd..e5135a4f9e5 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/ClassDefinitionParser.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.query2.definition; import com.evolveum.midpoint.prism.path.IdentifierPathSegment; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.path.ParentPathSegment; @@ -26,8 +27,10 @@ import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.query.definition.Any; import com.evolveum.midpoint.repo.sql.query.definition.JaxbName; +import com.evolveum.midpoint.repo.sql.query.definition.JaxbPath; import com.evolveum.midpoint.repo.sql.query.definition.JaxbType; import com.evolveum.midpoint.repo.sql.query.definition.OwnerGetter; +import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query.definition.QueryEntity; import com.evolveum.midpoint.repo.sql.query.definition.VirtualAny; import com.evolveum.midpoint.repo.sql.query.definition.VirtualCollection; @@ -51,6 +54,8 @@ import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; import java.util.Set; /** @@ -121,7 +126,7 @@ private JpaLinkDefinition parseMethod(Method method) { collectionSpecification = null; } - QName jaxbName = getJaxbName(method); + ItemPath itemPath = getJaxbName(method); String jpaName = getJpaName(method); Class jpaClass = getClass(returnedContentType); @@ -146,11 +151,11 @@ private JpaLinkDefinition parseMethod(Method method) { referencedJpaClass = RObject.class; } JpaReferenceDefinition targetDefinition = new JpaReferenceDefinition(jpaClass, referencedJpaClass); - linkDefinition = new JpaLinkDefinition<>(jaxbName, jpaName, collectionSpecification, embedded, targetDefinition); + linkDefinition = new JpaLinkDefinition<>(itemPath, jpaName, collectionSpecification, embedded, targetDefinition); } else if (isEntity(jpaClass)) { JpaEntityDefinition content = parseClass(jpaClass); boolean embedded = method.isAnnotationPresent(Embedded.class) || jpaClass.isAnnotationPresent(Embeddable.class); - linkDefinition = new JpaLinkDefinition(jaxbName, jpaName, collectionSpecification, embedded, content); + linkDefinition = new JpaLinkDefinition(itemPath, jpaName, collectionSpecification, embedded, content); } else { boolean lob = method.isAnnotationPresent(Lob.class); boolean enumerated = method.isAnnotationPresent(Enumerated.class); @@ -158,19 +163,21 @@ private JpaLinkDefinition parseMethod(Method method) { boolean indexed = method.isAnnotationPresent(Index.class); Class jaxbClass = getJaxbClass(method, jpaClass); - ItemPathSegment itemPathSegment; if (method.isAnnotationPresent(IdQueryProperty.class)) { if (collectionSpecification != null) { throw new IllegalStateException("ID property is not allowed to be multivalued; for method " + method); } - itemPathSegment = new IdentifierPathSegment(); - } else { - itemPathSegment = new NameItemPathSegment(jaxbName); + itemPath = new ItemPath(new IdentifierPathSegment()); + } else if (method.isAnnotationPresent(OwnerIdGetter.class)) { + if (collectionSpecification != null) { + throw new IllegalStateException("Owner ID property is not allowed to be multivalued; for method " + method); + } + itemPath = new ItemPath(new ParentPathSegment(), new IdentifierPathSegment()); } JpaPropertyDefinition propertyDefinition = new JpaPropertyDefinition(jpaClass, jaxbClass, lob, enumerated, indexed); // Note that properties are considered to be embedded - linkDefinition = new JpaLinkDefinition(itemPathSegment, jpaName, collectionSpecification, true, propertyDefinition); + linkDefinition = new JpaLinkDefinition(itemPath, jpaName, collectionSpecification, true, propertyDefinition); } return linkDefinition; } @@ -249,12 +256,19 @@ private boolean isEntity(Class type) { return type.getAnnotation(Entity.class) != null || type.getAnnotation(Embeddable.class) != null; } - private QName getJaxbName(Method method) { + private ItemPath getJaxbName(Method method) { if (method.isAnnotationPresent(JaxbName.class)) { JaxbName jaxbName = method.getAnnotation(JaxbName.class); - return new QName(jaxbName.namespace(), jaxbName.localPart()); + return new ItemPath(new QName(jaxbName.namespace(), jaxbName.localPart())); + } else if (method.isAnnotationPresent(JaxbPath.class)) { + JaxbPath jaxbPath = method.getAnnotation(JaxbPath.class); + List names = new ArrayList<>(jaxbPath.itemPath().length); + for (JaxbName jaxbName : jaxbPath.itemPath()) { + names.add(new QName(jaxbName.namespace(), jaxbName.localPart())); + } + return new ItemPath(names.toArray(new QName[0])); } else { - return new QName(SchemaConstantsGenerated.NS_COMMON, getPropertyName(method.getName())); + return new ItemPath(new QName(SchemaConstantsGenerated.NS_COMMON, getPropertyName(method.getName()))); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java index ebb1b47306f..c1459f45d53 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/IdQueryProperty.java @@ -23,6 +23,7 @@ /** * Target of "#" (ID) queries. + * Actually, a shorthand for @jaxbName(t:ID) * * @author mederly */ diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java index 927d9b9c7d0..523e8ae4cf0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaDataNodeDefinition.java @@ -30,17 +30,18 @@ * Defines piece of JPA data - entity, property, reference, or "any" container. Used to convert ItemPath to HQL query, * or, specifically, to a property path with left outer joins where appropriate. * - * The conversion works like running DFA (deterministic finite automaton) where - * data definitions are states, and ItemPathSegments are alphabet symbols. + * The conversion works like running state machine where data definitions are states, and transitions are labeled + * with non-empty ItemPaths. Input paths are used to navigate through states until all of input path is consumed. * - * In addition to recognize input words, this automaton produces HQL path and property joins. That's why - * each possible transition is labeled with (ItemPathSegment, JPA name, other transition data) tuple. - * ItemPathSegment is used to match the input word (path), while JPA name + other transition data, along + * In addition to recognize input paths, this automaton produces HQL path and property joins. That's why + * each possible transition is labeled with (ItemPath prefix, JPA name, other transition data) tuple. + * ItemPath prefix is used to match the input path, while JPA name + other transition data, along * with target state information (potentially) are used to generate HQL property path with appropriate join, * if necessary. * * Note that some transitions may have empty JPA name - when the data is contained directly in owner entity - * (e.g. metadata, construction, object extension, shadow attributes). + * (e.g. object extension, shadow attributes). Most transitions have single item paths. However, some have two, + * e.g. construction/resourceRef, owner/id, metadata/*. * * By other transition data we currently mean: collection specification, or "embedded" flag. * diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java index fa0a3ab19c0..c1e6556804e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaEntityDefinition.java @@ -54,7 +54,7 @@ public JpaEntityDefinition(Class jpaClass, Class jaxbClass) { } public void addDefinition(JpaLinkDefinition definition) { - JpaLinkDefinition oldDef = findRawLinkDefinition(definition.getItemPathSegment(), JpaDataNodeDefinition.class); + JpaLinkDefinition oldDef = findRawLinkDefinition(definition.getItemPath(), JpaDataNodeDefinition.class, true); if (oldDef != null) { definitions.remove(oldDef); } @@ -65,13 +65,19 @@ public void sortDefinitions() { Collections.sort(definitions, new LinkDefinitionComparator()); } - private JpaLinkDefinition findRawLinkDefinition(ItemPathSegment itemPathSegment, Class type) { - Validate.notNull(itemPathSegment, "ItemPathSegment must not be null."); + private JpaLinkDefinition findRawLinkDefinition(ItemPath itemPath, Class type, boolean exact) { + Validate.notNull(itemPath, "ItemPath must not be null."); Validate.notNull(type, "Definition type must not be null."); for (JpaLinkDefinition definition : definitions) { - if (!definition.matches(itemPathSegment)) { - continue; + if (exact) { + if (!definition.matchesExactly(itemPath)) { + continue; + } + } else { + if (!definition.matchesStartOf(itemPath)) { + continue; + } } if (type.isAssignableFrom(definition.getTargetClass())) { return definition; @@ -147,12 +153,12 @@ public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDef throw new QueryException("'@' path segment cannot be used in the context of an entity " + this); } - JpaLinkDefinition link = findRawLinkDefinition(path.first(), JpaDataNodeDefinition.class); + JpaLinkDefinition link = findRawLinkDefinition(path, JpaDataNodeDefinition.class, false); if (link == null) { return null; } else { link.resolveEntityPointer(); - return new DataSearchResult(link, path.tail()); + return new DataSearchResult(link, path.tail(link.getItemPath().size())); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java index a71055c9579..dddbcf900f0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/JpaLinkDefinition.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.Visitor; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.util.DebugDumpable; @@ -31,30 +32,42 @@ */ public class JpaLinkDefinition implements Visitable, DebugDumpable { - private ItemPathSegment itemPathSegment; + private ItemPath itemPath; // usually single item, but might be longer private String jpaName; // beware - null for "same entity" transitions (metadata, construction, ...) private CollectionSpecification collectionSpecification; // null if single valued private boolean embedded; private D targetDefinition; - public JpaLinkDefinition(ItemPathSegment itemPathSegment, String jpaName, CollectionSpecification collectionSpecification, boolean embedded, D targetDefinition) { - Validate.notNull(itemPathSegment, "itemPathSegment"); + public JpaLinkDefinition(ItemPath itemPath, String jpaName, CollectionSpecification collectionSpecification, boolean embedded, D targetDefinition) { + Validate.notNull(itemPath, "itemPath"); Validate.notNull(targetDefinition, "targetDefinition"); - this.itemPathSegment = itemPathSegment; + this.itemPath = itemPath; this.jpaName = jpaName; this.collectionSpecification = collectionSpecification; this.embedded = embedded; this.targetDefinition = targetDefinition; } + public JpaLinkDefinition(ItemPathSegment itemPathSegment, String jpaName, CollectionSpecification collectionSpecification, boolean embedded, D targetDefinition) { + this(new ItemPath(itemPathSegment), jpaName, collectionSpecification, embedded, targetDefinition); + Validate.notNull(itemPathSegment, "itemPathSegment"); + } + public JpaLinkDefinition(QName jaxbName, String jpaName, CollectionSpecification collectionSpecification, boolean embedded, D targetDefinition) { this(new NameItemPathSegment(jaxbName), jpaName, collectionSpecification, embedded, targetDefinition); Validate.notNull(jaxbName, "jaxbName"); // "this" must be the first - validation is better late than never ;) } + public ItemPath getItemPath() { + return itemPath; + } + public ItemPathSegment getItemPathSegment() { - return itemPathSegment; + if (itemPath.size() != 1) { + throw new IllegalStateException("Expected single-item path, found '" + itemPath + "' instead."); + } + return itemPath.first(); } public String getJpaName() { @@ -73,8 +86,12 @@ public D getTargetDefinition() { return targetDefinition; } - public boolean matches(ItemPathSegment itemPathSegment) { - return this.itemPathSegment.equivalent(itemPathSegment); + public boolean matchesExactly(ItemPath itemPath) { + return this.itemPath.equivalent(itemPath); + } + + public boolean matchesStartOf(ItemPath itemPath) { + return itemPath.startsWith(this.itemPath); } public Class getTargetClass() { @@ -114,7 +131,7 @@ public String debugDump(int indent) { } private void dumpLink(StringBuilder sb) { - sb.append(itemPathSegment.toString()).append(" => ").append(jpaName); + sb.append(itemPath).append(" => ").append(jpaName); if (collectionSpecification != null) { sb.append(collectionSpecification.getShortInfo()); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java index 6c6eb91b6d6..da573db779a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/definition/LinkDefinitionComparator.java @@ -25,6 +25,14 @@ public class LinkDefinitionComparator implements Comparator { @Override public int compare(JpaLinkDefinition o1, JpaLinkDefinition o2) { + + // longer paths have to come first, in order for matching to work + + int sizeDiff = o1.getItemPath().size() - o2.getItemPath().size(); + if (sizeDiff != 0) { + return -sizeDiff; + } + JpaDataNodeDefinition target1 = o1.getTargetDefinition(); JpaDataNodeDefinition target2 = o2.getTargetDefinition(); From 361e8b33f23adfa1426f34cf6e383d3a9cc6e988 Mon Sep 17 00:00:00 2001 From: honchar Date: Mon, 7 Dec 2015 10:56:49 +0100 Subject: [PATCH 069/116] Associations editable panel. not finished yet --- .../web/component/form/ValueChoosePanel.java | 45 +++++++++++++------ .../web/component/prism/PrismValuePanel.java | 34 ++++++++------ .../midpoint/web/util/WebMiscUtil.java | 3 +- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java index e55bf598f2a..827b4b42823 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java @@ -4,10 +4,13 @@ import java.util.Collection; import java.util.List; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPage; import com.evolveum.midpoint.web.util.WebMiscUtil; +import javafx.beans.property.ObjectProperty; import org.apache.wicket.Page; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -112,11 +115,17 @@ public void onClick(AjaxRequestTarget target) { // } protected void replaceIfEmpty(Object object) { - boolean added = false; - ObjectReferenceType ort = ObjectTypeUtil.createObjectRef((ObjectType) object); - ort.setTargetName(((ObjectType) object).getName()); - getModel().setObject((T)ort.asReferenceValue()); - + T old = getModelObject(); + ObjectReferenceType ort = ObjectTypeUtil.createObjectRef((ObjectType) object); + ort.setTargetName(((ObjectType) object).getName()); + if (old instanceof PrismPropertyValue) { // let's assume we are working with associations panel +// ObjectType newValue= (ObjectType)object; +// getModel().setObject((T)newValue); + //TODO + getModel().setObject((T) ort.asReferenceValue()); + } else { + getModel().setObject((T) ort.asReferenceValue()); + } } protected void initDialog(final Class type, List values, ObjectQuery query) { @@ -125,8 +134,6 @@ protected void initDialog(final Class type, List values, initUserOrgDialog(); } else { initGenericDialog(type, values, query); - - } } @@ -162,6 +169,7 @@ public ObjectQuery getDataProviderQuery() { @Override public boolean isSearchEnabled() { + //TODO don't commit return false; } @@ -304,13 +312,22 @@ protected void choosePerformed(AjaxRequestTarget target, C object) { protected boolean isObjectUnique(C object) { // for(T o: ){ - PrismReferenceValue old = (PrismReferenceValue)getModelObject(); - if (old == null || old.isEmpty()){ - return true; - } - if (old.getOid().equals(object.getOid())) { - return false; - } + T old = getModelObject(); + if (old instanceof PrismPropertyValue){ + if (old == null || ((PrismPropertyValue)old).isEmpty()){ + return true; + } + if (((PrismPropertyValue)old).getValue().equals(object.asPrismObject().getValue())) { + return false; + } + } else { + if (old == null || ((PrismReferenceValue)old).isEmpty()){ + return true; + } + if (((PrismReferenceValue)old).getOid().equals(object.getOid())) { + return false; + }} + // } return true; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index 7ba49bf0c56..20023d5f2d2 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -397,6 +397,8 @@ private DateValidator getActivationRangeValidator(Form form, ItemPath path) { // normally this method returns an InputPanel; // however, for some special readonly types (like ObjectDeltaType) it will return a Panel private Panel createTypedInputComponent(String id) { +// ValueWrapper valueWrapper = model.getObject(); +// ItemWrapper itemWrapper = final Item item = model.getObject().getItem().getItem(); Panel panel = null; @@ -421,12 +423,12 @@ private Panel createTypedInputComponent(String id) { PrismProperty kindItem = (PrismProperty)assocContainer.findItem(ShadowType.F_KIND); PrismProperty intentItem = (PrismProperty)assocContainer.findItem(ShadowType.F_INTENT); PrismObject resource = ((ShadowType)containerWrapper.getObject().getObject().asObjectable()).getResource().asPrismObject(); - ObjectQuery query = getAssociationsSearchQuery(resource, + ObjectQuery query = getAssociationsSearchQuery(prismContext, resource, objectClassItem, kindItem, intentItem); List> values = loadAssociationShadows(query); return new ValueChoosePanel(id, - new PropertyModel<>(model, "value"), values, false, ShadowType.class, query, getAssociationsSearchOptions()); + new PropertyModel<>(model, "value"), item.getValues(), false, ShadowType.class, query, getAssociationsSearchOptions()); } } @@ -772,6 +774,23 @@ private void removeValue(AjaxRequestTarget target) { target.add(parent.getParent()); } + private ObjectQuery getAssociationsSearchQuery(PrismContext prismContext, PrismObject resource, PrismProperty objectClass, PrismProperty kind, + PrismProperty intent){ + try { + ObjectFilter andFilter = AndFilter.createAnd( + EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, objectClass.getRealValue()), + EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class, prismContext, kind.getRealValue()), + EqualFilter.createEqual(ShadowType.F_INTENT, ShadowType.class, prismContext, intent.getRealValue()), + RefFilter.createReferenceEqual(new ItemPath(ShadowType.F_RESOURCE_REF), ShadowType.class, prismContext, resource.getOid())); + ObjectQuery query = ObjectQuery.createObjectQuery(andFilter); + return query; + } catch (SchemaException ex) { + LoggingUtils.logException(LOGGER, "Unable to create associations search query", ex); + return null; + } + + } + private List> loadAssociationShadows(ObjectQuery query) { Task task = pageBase.createSimpleTask(OPERATION_LOAD_ASSOC_SHADOWS); OperationResult result = new OperationResult(OPERATION_LOAD_ASSOC_SHADOWS); @@ -789,17 +808,6 @@ private List> loadAssociationShadows(ObjectQuery query) return assocShadows; } - private ObjectQuery getAssociationsSearchQuery(PrismObject resource, PrismProperty objectClass, PrismProperty kind, - PrismProperty intent){ - ObjectFilter andFilter = AndFilter.createAnd( - EqualFilter.createEqual(new ItemPath(ShadowType.F_OBJECT_CLASS), objectClass), - EqualFilter.createEqual(new ItemPath(ShadowType.F_KIND), kind), - EqualFilter.createEqual(new ItemPath(ShadowType.F_INTENT), intent), - RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, resource)); - ObjectQuery query = ObjectQuery.createObjectQuery(andFilter); - return query; - } - private Collection> getAssociationsSearchOptions(){ Collection> options = new ArrayList>(); options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createRaw())); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java index d4af436056f..243f8d57ae8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java @@ -854,7 +854,8 @@ public static T theSameForPage(T object, PageReference con String path = object.getPageRelativePath(); T retval = (T) containingPage.get(path); if (retval == null) { - throw new IllegalStateException("There is no component like " + object + " (path '" + path + "') on " + containingPage); + return object; +// throw new IllegalStateException("There is no component like " + object + " (path '" + path + "') on " + containingPage); } return retval; } From 1768eb553347bc718bde7b5fdf5bbacb622a4611 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 7 Dec 2015 14:54:17 +0100 Subject: [PATCH 070/116] Adding db constraint allowing at most one decision per stage+reviewer in a given case. --- .../common/container/RAccessCertificationDecision.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java index 1364f72d25d..086534b464c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java @@ -42,7 +42,13 @@ @JaxbType(type = AccessCertificationDecisionType.class) @Entity @IdClass(RL2ContainerId.class) -@Table(name = "m_acc_cert_decision", indexes = { +@Table(name = "m_acc_cert_decision", + uniqueConstraints = + @UniqueConstraint( + name = "uc_case_stage_reviewer", + columnNames = {"owner_owner_oid", "owner_id", "stageNumber", "reviewerRef_targetOid" }), + + indexes = { // @Index(name = "iObjectRefTargetOid", columnList = "objectRef_targetOid"), // @Index(name = "iTargetRefTargetOid", columnList = "targetRef_targetOid") }) From 02efc28d99daf0d008bf1302d4fcd0714f75928f Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 7 Dec 2015 17:03:26 +0100 Subject: [PATCH 071/116] Review filters because of changed non-singleton items filtering semantics. --- .../midpoint/prism/query/ExistsFilter.java | 8 ++ .../midpoint/prism/query/TypeFilter.java | 8 ++ .../prism/query/builder/FilterBuilder.java | 31 ------- .../prism/query/builder/QueryBuilder.java | 12 --- .../midpoint/prism/query/TestObjectQuery.java | 27 ++---- .../midpoint/schema/util/ObjectQueryUtil.java | 3 +- .../sync/FocusValidityScannerTaskHandler.java | 93 +++++++------------ .../trigger/TriggerScannerTaskHandler.java | 61 ++++++------ .../provisioning/impl/ShadowCache.java | 7 +- .../repo/sql/QueryInterpreter2Test.java | 45 +++++++-- 10 files changed, 127 insertions(+), 168 deletions(-) delete mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java index ab01d06bbee..92cd8e37a27 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExistsFilter.java @@ -155,4 +155,12 @@ public String toString() { sb.append(")"); return sb.toString(); } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + if (filter != null) { + visitor.visit(filter); + } + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java index 91cdbbecd3c..fa9f6bf62e9 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/TypeFilter.java @@ -124,4 +124,12 @@ public String toString() { sb.append(")"); return sb.toString(); } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + if (filter != null) { + visitor.visit(filter); + } + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java deleted file mode 100644 index 089730da5f7..00000000000 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/FilterBuilder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.prism.query.builder; - -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.NotFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.OrFilter; - -/** - * @author mederly - */ -public class FilterBuilder { - - - -} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java index 004f023ed7b..f0c868b3fb6 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/QueryBuilder.java @@ -18,20 +18,8 @@ import com.evolveum.midpoint.prism.ComplexTypeDefinition; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.AllFilter; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.NotFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.util.exception.SchemaException; -import org.apache.commons.lang.Validate; - -import java.util.ArrayList; -import java.util.List; /** * Here is the language structure: diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestObjectQuery.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestObjectQuery.java index 2c5ac8d31f0..3347e7ab755 100644 --- a/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestObjectQuery.java +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/query/TestObjectQuery.java @@ -16,17 +16,6 @@ package com.evolveum.midpoint.prism.query; -import static com.evolveum.midpoint.prism.PrismInternalTestUtil.DEFAULT_NAMESPACE_PREFIX; - -import java.io.File; -import java.io.IOException; - -import org.springframework.beans.factory.annotation.Autowired; -import org.testng.AssertJUnit; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.xml.sax.SAXException; - import com.evolveum.midpoint.prism.PrismInternalTestUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.foo.UserType; @@ -34,17 +23,17 @@ import com.evolveum.midpoint.prism.match.MatchingRuleRegistryFactory; import com.evolveum.midpoint.prism.match.StringIgnoreCaseMatchingRule; import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrFilter; -import com.evolveum.midpoint.prism.query.RefFilter; -import com.evolveum.midpoint.prism.query.SubstringFilter; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.testng.AssertJUnit; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +import java.io.IOException; + +import static com.evolveum.midpoint.prism.PrismInternalTestUtil.DEFAULT_NAMESPACE_PREFIX; public class TestObjectQuery { diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java index d2bfbd8f189..cbdb2a67cec 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectQueryUtil.java @@ -175,7 +175,8 @@ public void visit(ObjectFilter filter) { filter.accept(visitor); return hasAllDefinitions.booleanValue(); } - + + // TODO what about OidIn here? public static void assertPropertyOnly(ObjectFilter filter, final String message) { Visitor visitor = new Visitor() { @Override diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java index 15105f4ef44..db37edd47e8 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java @@ -15,13 +15,6 @@ */ package com.evolveum.midpoint.model.impl.sync; -import javax.annotation.PostConstruct; -import javax.xml.datatype.XMLGregorianCalendar; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import com.evolveum.midpoint.model.api.PolicyViolationException; import com.evolveum.midpoint.model.impl.ModelConstants; import com.evolveum.midpoint.model.impl.lens.Clockwork; @@ -31,31 +24,31 @@ import com.evolveum.midpoint.model.impl.util.AbstractScannerTaskHandler; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.GreaterFilter; -import com.evolveum.midpoint.prism.query.LessFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrFilter; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.provisioning.api.ProvisioningService; import com.evolveum.midpoint.schema.result.OperationConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskRunResult; -import com.evolveum.midpoint.util.exception.CommonException; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.xml.datatype.XMLGregorianCalendar; + +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType.F_VALID_FROM; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType.F_VALID_TO; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType.F_ACTIVATION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType.F_ASSIGNMENT; /** * @@ -106,43 +99,29 @@ protected ObjectQuery createQuery(AbstractScannerResultHandler handler XMLGregorianCalendar lastScanTimestamp = handler.getLastScanTimestamp(); XMLGregorianCalendar thisScanTimestamp = handler.getThisScanTimestamp(); if (lastScanTimestamp == null) { - filter = OrFilter.createOr( - LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, - thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, - thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), - focusObjectDef, thisScanTimestamp, true), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), - focusObjectDef, thisScanTimestamp, true) - ); + filter = QueryBuilder.queryFor(FocusType.class, prismContext) + .item(F_ACTIVATION, F_VALID_FROM).le(thisScanTimestamp) + .or().item(F_ACTIVATION, F_VALID_TO).le(thisScanTimestamp) + .or().exists(F_ASSIGNMENT) + .block() + .item(AssignmentType.F_ACTIVATION, F_VALID_FROM).le(thisScanTimestamp) + .or().item(AssignmentType.F_ACTIVATION, F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .buildFilter(); } else { - filter = OrFilter.createOr( - AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, - lastScanTimestamp, false), - LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), focusObjectDef, - thisScanTimestamp, true) - ), - AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, - lastScanTimestamp, false), - LessFilter.createLess(new ItemPath(FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), focusObjectDef, - thisScanTimestamp, true) - ), - AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), - focusObjectDef, lastScanTimestamp, false), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_FROM), - focusObjectDef, thisScanTimestamp, true) - ), - AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), - focusObjectDef, lastScanTimestamp, false), - LessFilter.createLess(new ItemPath(FocusType.F_ASSIGNMENT, FocusType.F_ACTIVATION, ActivationType.F_VALID_TO), - focusObjectDef, thisScanTimestamp, true) - ) - ); + filter = QueryBuilder.queryFor(FocusType.class, prismContext) + .item(F_ACTIVATION, F_VALID_FROM).gt(lastScanTimestamp) + .and().item(F_ACTIVATION, F_VALID_FROM).le(thisScanTimestamp) + .or().item(F_ACTIVATION, F_VALID_TO).gt(lastScanTimestamp) + .and().item(F_ACTIVATION, F_VALID_TO).le(thisScanTimestamp) + .or().exists(F_ASSIGNMENT) + .block() + .item(AssignmentType.F_ACTIVATION, F_VALID_FROM).gt(lastScanTimestamp) + .and().item(AssignmentType.F_ACTIVATION, F_VALID_FROM).le(thisScanTimestamp) + .or().item(AssignmentType.F_ACTIVATION, F_VALID_TO).gt(lastScanTimestamp) + .and().item(AssignmentType.F_ACTIVATION, F_VALID_TO).le(thisScanTimestamp) + .endBlock() + .buildFilter(); } query.setFilter(filter); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/trigger/TriggerScannerTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/trigger/TriggerScannerTaskHandler.java index a09c1c73704..117d8aecdd0 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/trigger/TriggerScannerTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/trigger/TriggerScannerTaskHandler.java @@ -15,52 +15,41 @@ */ package com.evolveum.midpoint.model.impl.trigger; -import java.util.Collection; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.xml.datatype.DatatypeConstants; -import javax.xml.datatype.XMLGregorianCalendar; - -import com.evolveum.midpoint.prism.delta.ChangeType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import com.evolveum.midpoint.model.api.PolicyViolationException; import com.evolveum.midpoint.model.impl.util.AbstractScannerResultHandler; import com.evolveum.midpoint.model.impl.util.AbstractScannerTaskHandler; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.GreaterFilter; import com.evolveum.midpoint.prism.query.LessFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskRunResult; -import com.evolveum.midpoint.util.exception.CommonException; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.XMLGregorianCalendar; +import java.util.Collection; +import java.util.List; + +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_TRIGGER; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType.F_TIMESTAMP; /** * @@ -101,17 +90,19 @@ protected ObjectQuery createQuery(AbstractScannerResultHandler handl ObjectQuery query = new ObjectQuery(); ObjectFilter filter; PrismObjectDefinition focusObjectDef = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(UserType.class); - PrismContainerDefinition triggerContainerDef = focusObjectDef.findContainerDefinition(ObjectType.F_TRIGGER); + PrismContainerDefinition triggerContainerDef = focusObjectDef.findContainerDefinition(F_TRIGGER); if (handler.getLastScanTimestamp() == null) { - filter = LessFilter.createLess(new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP), focusObjectDef, + filter = LessFilter.createLess(new ItemPath(F_TRIGGER, F_TIMESTAMP), focusObjectDef, handler.getThisScanTimestamp(), true); } else { - filter = AndFilter.createAnd( - GreaterFilter.createGreater(new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP), focusObjectDef, - handler.getLastScanTimestamp(), false), - LessFilter.createLess(new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP), focusObjectDef, - handler.getThisScanTimestamp(), true)); + filter = QueryBuilder.queryFor(ObjectType.class, prismContext) + .exists(F_TRIGGER) + .block() + .item(F_TIMESTAMP).gt(handler.getLastScanTimestamp()) + .and().item(F_TIMESTAMP).le(handler.getThisScanTimestamp()) + .endBlock() + .buildFilter(); } query.setFilter(filter); @@ -137,7 +128,7 @@ protected boolean handleObject(PrismObject object, Task workerTask, private void fireTriggers(AbstractScannerResultHandler handler, PrismObject object, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ObjectAlreadyExistsException, ConfigurationException, PolicyViolationException, SecurityViolationException { - PrismContainer triggerContainer = object.findContainer(ObjectType.F_TRIGGER); + PrismContainer triggerContainer = object.findContainer(F_TRIGGER); if (triggerContainer == null) { LOGGER.warn("Strange thing, attempt to fire triggers on {}, but it does not have trigger container", object); } else { @@ -202,7 +193,7 @@ private void fireTrigger(String handlerUri, PrismObject object, Task private void removeTrigger(PrismObject object, PrismContainerValue triggerCVal, Task task) { PrismContainerDefinition triggerContainerDef = triggerCVal.getParent().getDefinition(); - ContainerDelta triggerDelta = (ContainerDelta) triggerContainerDef.createEmptyDelta(new ItemPath(ObjectType.F_TRIGGER)); + ContainerDelta triggerDelta = (ContainerDelta) triggerContainerDef.createEmptyDelta(new ItemPath(F_TRIGGER)); triggerDelta.addValuesToDelete(triggerCVal.clone()); Collection modifications = MiscSchemaUtil.createCollection(triggerDelta); // This is detached result. It will not take part of the task result. We do not really care. diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java index b51bcbe16d8..cda05ff5f8b 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java @@ -784,11 +784,10 @@ ObjectQuery createAttributeQuery(ObjectQuery query) throws SchemaException { } ObjectQuery attributeQuery = null; - List attributeFilter = new ArrayList(); - if (filter instanceof AndFilter){ + if (filter instanceof AndFilter) { List conditions = ((AndFilter) filter).getConditions(); - attributeFilter = createAttributeQueryInternal(conditions); + List attributeFilter = createAttributeQueryInternal(conditions); if (attributeFilter.size() > 1){ attributeQuery = ObjectQuery.createObjectQuery(AndFilter.createAnd(attributeFilter)); } else if (attributeFilter.size() < 1){ @@ -840,7 +839,7 @@ private List createAttributeQueryInternal(List :timestamp and t.timestamp <= :timestamp2 )\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test170QueryAssignmentActivationAdministrativeStatus() throws Exception { Session session = open(); @@ -1208,7 +1235,7 @@ public void test200QueryTriggerTimestampDoubleWrong() throws Exception { SchemaRegistry registry = prismContext.getSchemaRegistry(); PrismObjectDefinition objectDef = registry.findObjectDefinitionByCompileTimeClass(ObjectType.class); - ItemPath triggerPath = new ItemPath(ObjectType.F_TRIGGER, TriggerType.F_TIMESTAMP); + ItemPath triggerPath = new ItemPath(ObjectType.F_TRIGGER, F_TIMESTAMP); ObjectFilter greater = GreaterFilter.createGreater(triggerPath, objectDef, thisScanTimestamp, false); ObjectFilter lesser = LessFilter.createLess(triggerPath, objectDef, thisScanTimestamp, false); AndFilter and = AndFilter.createAnd(greater, lesser); From ee65f2f4ffc2e34d871b515308ce38dcbbe2c430 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 7 Dec 2015 17:15:51 +0100 Subject: [PATCH 072/116] Extending object template tests --- .../midpoint/prism/delta/ItemDelta.java | 10 +- ...stractInitializedModelIntegrationTest.java | 11 +- .../model/intest/TestUserTemplate.java | 145 +++++++++++++++++- 3 files changed, 156 insertions(+), 10 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java index 405c574ca9e..480ca2de743 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Evolveum + * Copyright (c) 2010-2015 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -515,9 +515,11 @@ public void setValueToReplace(V newValue) { } else { valuesToReplace.clear(); } - valuesToReplace.add(newValue); - newValue.setParent(this); - newValue.recompute(); + if (newValue != null) { + valuesToReplace.add(newValue); + newValue.setParent(this); + newValue.recompute(); + } } public void mergeValuesToReplace(Collection newValues) { diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java index 5d04941d672..4c440debc30 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractInitializedModelIntegrationTest.java @@ -359,11 +359,18 @@ protected void setDefaultUserTemplate(String userTemplateOid) PrismObjectDefinition objectDefinition = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(SystemConfigurationType.class); - PrismReferenceValue userTemplateRefVal = new PrismReferenceValue(userTemplateOid); + Collection modifications; - Collection modifications = ReferenceDelta.createModificationReplaceCollection( + if (userTemplateOid == null) { + modifications = ReferenceDelta.createModificationReplaceCollection( + SystemConfigurationType.F_DEFAULT_USER_TEMPLATE_REF, + objectDefinition, null); + } else { + PrismReferenceValue userTemplateRefVal = new PrismReferenceValue(userTemplateOid); + modifications = ReferenceDelta.createModificationReplaceCollection( SystemConfigurationType.F_DEFAULT_USER_TEMPLATE_REF, objectDefinition, userTemplateRefVal); + } OperationResult result = new OperationResult("Aplying default user template"); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java index ed32a6c4f6e..287a693f367 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java @@ -661,12 +661,53 @@ public void test155ModifyJackOrganizationalUnitFD001() throws Exception { // IntegrationTestTools.assertNoExtensionProperty(userJack, PIRACY_COLORS); } + /** + * Reconcile user Jack, see that everything is OK. + */ + @Test + public void test156ReconcileJack() throws Exception { + final String TEST_NAME = "test156ReconcileJack"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + reconcileUser(USER_JACK_OID, task, result); + + // THEN + PrismObject userJack = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); + display("User after", userJack); + + PrismAsserts.assertPropertyValue(userJack, UserType.F_DESCRIPTION, "Where's the rum?"); + assertAssignedAccount(userJack, RESOURCE_DUMMY_BLUE_OID); + assertNotAssignedRole(userJack, ROLE_PIRATE_OID); + assertAssignedOrg(userJack, ORG_MINISTRY_OF_RUM_OID); + assertHasOrg(userJack, ORG_MINISTRY_OF_RUM_OID); + + assertOnDemandOrgAssigned("FD001", userJack); + + assertAssignments(userJack, 3); + + UserType userJackType = userJack.asObjectable(); + assertEquals("Unexpected number of accountRefs", 1, userJackType.getLinkRef().size()); + + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertEquals("Wrong costCenter", "X000", userJackType.getCostCenter()); + assertEquals("Wrong employee number", jackEmployeeNumber, userJackType.getEmployeeNumber()); + assertEquals("Wrong telephone number", "1 222 3456789", userJackType.getTelephoneNumber()); + assertNull("Unexpected title: "+userJackType.getTitle(), userJackType.getTitle()); + } + /** * Creates two orgs on demand. */ @Test - public void test156ModifyJackOrganizationalUnitFD0023() throws Exception { - final String TEST_NAME = "test156ModifyJackOrganizationalUnitFD0023"; + public void test157ModifyJackOrganizationalUnitFD0023() throws Exception { + final String TEST_NAME = "test157ModifyJackOrganizationalUnitFD0023"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN @@ -708,8 +749,8 @@ public void test156ModifyJackOrganizationalUnitFD0023() throws Exception { } @Test - public void test157ModifyJackDeleteOrganizationalUnitFD002() throws Exception { - final String TEST_NAME = "test157ModifyJackDeleteOrganizationalUnitFD002"; + public void test159ModifyJackDeleteOrganizationalUnitFD002() throws Exception { + final String TEST_NAME = "test159ModifyJackDeleteOrganizationalUnitFD002"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN @@ -1052,4 +1093,100 @@ public void test900DeleteUser() throws Exception { TestUtil.assertFailure(result); } + @Test + public void test950CreateUserJackWithoutTemplate() throws Exception { + final String TEST_NAME = "test950CreateUserJackWithoutTemplate"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + setDefaultUserTemplate(null); + + Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + addObject(USER_JACK_FILE, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject userJack = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); + display("User after", userJack); + + PrismAsserts.assertPropertyValue(userJack, UserType.F_DESCRIPTION, "Where's the rum?"); + assertAssignments(userJack, 0); + + UserType userJackType = userJack.asObjectable(); + assertEquals("Unexpected number of accountRefs", 0, userJackType.getLinkRef().size()); + + PrismAsserts.assertNoItem(userJack, UserType.F_ORGANIZATIONAL_UNIT); + + } + + /** + * Would creates org on demand if the template would be active. But it is not. + */ + @Test + public void test952ModifyJackOrganizationalUnitFD004() throws Exception { + final String TEST_NAME = "test952ModifyJackOrganizationalUnitFD004"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + modifyUserAdd(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("FD004")); + + // THEN + PrismObject userJack = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); + display("User after", userJack); + + PrismAsserts.assertPropertyValue(userJack, UserType.F_DESCRIPTION, "Where's the rum?"); + PrismAsserts.assertPropertyValue(userJack, UserType.F_ORGANIZATIONAL_UNIT, PrismTestUtil.createPolyString("FD004")); + + assertAssignments(userJack, 0); + + UserType userJackType = userJack.asObjectable(); + assertEquals("Unexpected number of accountRefs", 0, userJackType.getLinkRef().size()); + + PrismObject org = findObjectByName(OrgType.class, "FD004"); + assertNull("Found org "+org+" but not expecting it", org); + } + + /** + * Set the template. Reconcile the user that should have org created on demand (but does not). + * The org should be created. + */ + @Test + public void test960ReconcileUserJackWithTemplate() throws Exception { + final String TEST_NAME = "test960ModifyUserJackWithTemplate"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + setDefaultUserTemplate(USER_TEMPLATE_COMPLEX_OID); + + Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + reconcileUser(USER_JACK_OID, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + PrismObject userJack = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); + display("User after", userJack); + + PrismAsserts.assertPropertyValue(userJack, UserType.F_DESCRIPTION, "Where's the rum?"); + assertAssignedAccount(userJack, RESOURCE_DUMMY_BLUE_OID); + assertOnDemandOrgAssigned("FD004", userJack); + + assertAssignments(userJack, 2); + + UserType userJackType = userJack.asObjectable(); + assertEquals("Unexpected number of accountRefs", 1, userJackType.getLinkRef().size()); + + } } From 90315d46270834d636551c3c9f7936536160b70a Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 7 Dec 2015 18:11:43 +0100 Subject: [PATCH 073/116] Implemented some missing pieces of new query api. --- .../prism/query/builder/R_Filter.java | 64 ++++----- .../query/builder/S_AtomicFilterEntry.java | 18 +-- .../repo/sql/QueryInterpreter2Test.java | 123 +++++++++++++++--- 3 files changed, 149 insertions(+), 56 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java index 434ec8a8611..861a0a226a6 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/R_Filter.java @@ -22,19 +22,7 @@ import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.AllFilter; -import com.evolveum.midpoint.prism.query.AndFilter; -import com.evolveum.midpoint.prism.query.ExistsFilter; -import com.evolveum.midpoint.prism.query.NoneFilter; -import com.evolveum.midpoint.prism.query.NotFilter; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectOrdering; -import com.evolveum.midpoint.prism.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrFilter; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.query.TypeFilter; -import com.evolveum.midpoint.prism.query.UndefinedFilter; +import com.evolveum.midpoint.prism.query.*; import com.evolveum.midpoint.util.exception.SchemaException; import org.apache.commons.lang.Validate; @@ -180,48 +168,62 @@ public S_AtomicFilterExit undefined() throws SchemaException { // TODO ............................................. @Override - public S_AtomicFilterExit id(String... identifiers) { - return null; + public S_AtomicFilterExit id(String... identifiers) throws SchemaException { + return addSubfilter(InOidFilter.createInOid(identifiers)); } @Override - public S_AtomicFilterExit id(long... identifiers) { - return null; + public S_AtomicFilterExit id(long... identifiers) throws SchemaException { + List ids = longsToStrings(identifiers); + return addSubfilter(InOidFilter.createInOid(ids)); + } + + private List longsToStrings(long[] identifiers) { + List ids = new ArrayList<>(identifiers.length); + for (long id : identifiers) { + ids.add(String.valueOf(id)); + } + return ids; } @Override - public S_AtomicFilterExit ownerId(String... identifiers) { - return null; + public S_AtomicFilterExit ownerId(String... identifiers) throws SchemaException { + return addSubfilter(InOidFilter.createOwnerHasOidIn(identifiers)); } @Override - public S_AtomicFilterExit ownerId(long... identifiers) { - return null; + public S_AtomicFilterExit ownerId(long... identifiers) throws SchemaException { + return addSubfilter(InOidFilter.createOwnerHasOidIn(longsToStrings(identifiers))); } @Override - public S_AtomicFilterExit isDirectChildOf(PrismReferenceValue value) { - return null; + public S_AtomicFilterExit isDirectChildOf(PrismReferenceValue value) throws SchemaException { + OrgFilter orgFilter = OrgFilter.createOrg(value, OrgFilter.Scope.ONE_LEVEL); + return addSubfilter(orgFilter); } @Override - public S_AtomicFilterExit isChildOf(PrismReferenceValue value) { - return null; + public S_AtomicFilterExit isChildOf(PrismReferenceValue value) throws SchemaException { + OrgFilter orgFilter = OrgFilter.createOrg(value, OrgFilter.Scope.SUBTREE); + return addSubfilter(orgFilter); } @Override - public S_AtomicFilterExit isDirectChildOf(String oid) { - return null; + public S_AtomicFilterExit isDirectChildOf(String oid) throws SchemaException { + OrgFilter orgFilter = OrgFilter.createOrg(oid, OrgFilter.Scope.ONE_LEVEL); + return addSubfilter(orgFilter); } @Override - public S_AtomicFilterExit isChildOf(String oid) { - return null; + public S_AtomicFilterExit isChildOf(String oid) throws SchemaException { + OrgFilter orgFilter = OrgFilter.createOrg(oid, OrgFilter.Scope.SUBTREE); + return addSubfilter(orgFilter); } @Override - public S_AtomicFilterExit isRoot() { - return null; + public S_AtomicFilterExit isRoot() throws SchemaException { + OrgFilter orgFilter = OrgFilter.createRootOrg(); + return addSubfilter(orgFilter); } @Override diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java index 4e617238873..1368db2c731 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/builder/S_AtomicFilterEntry.java @@ -33,15 +33,15 @@ public interface S_AtomicFilterEntry { S_AtomicFilterExit undefined() throws SchemaException; S_ConditionEntry item(QName... names) throws SchemaException; S_ConditionEntry item(ItemPath itemPath, ItemDefinition itemDefinition) throws SchemaException; - S_AtomicFilterExit id(String... identifiers); - S_AtomicFilterExit id(long... identifiers); - S_AtomicFilterExit ownerId(String... identifiers); - S_AtomicFilterExit ownerId(long... identifiers); - S_AtomicFilterExit isDirectChildOf(PrismReferenceValue value); - S_AtomicFilterExit isChildOf(PrismReferenceValue value); - S_AtomicFilterExit isDirectChildOf(String oid); - S_AtomicFilterExit isChildOf(String oid); - S_AtomicFilterExit isRoot(); + S_AtomicFilterExit id(String... identifiers) throws SchemaException; + S_AtomicFilterExit id(long... identifiers) throws SchemaException; + S_AtomicFilterExit ownerId(String... identifiers) throws SchemaException; + S_AtomicFilterExit ownerId(long... identifiers) throws SchemaException; + S_AtomicFilterExit isDirectChildOf(PrismReferenceValue value) throws SchemaException; + S_AtomicFilterExit isChildOf(PrismReferenceValue value) throws SchemaException; + S_AtomicFilterExit isDirectChildOf(String oid) throws SchemaException; + S_AtomicFilterExit isChildOf(String oid) throws SchemaException; + S_AtomicFilterExit isRoot() throws SchemaException; S_FilterEntryOrEmpty block(); S_FilterEntry type(Class type) throws SchemaException; S_FilterEntry exists(QName... names) throws SchemaException; diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 50ac6bef831..49eff0e5753 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -1345,12 +1345,8 @@ public void test320CountTaskOrderByName() throws Exception { public void test330InOidTest() throws Exception { Session session = open(); try { - InOidFilter filter = InOidFilter.createInOid(Arrays.asList("1", "2")); - - ObjectQuery query = ObjectQuery.createObjectQuery(filter); - -// ObjectQuery query1 = QueryBuilder.queryFor(ObjectType.class, prismContext) -// .id("1", "2").build(); + ObjectQuery query = QueryBuilder.queryFor(ObjectType.class, prismContext) + .id("1", "2").build(); String real = getInterpretedQuery2(session, ObjectType.class, query, false); String expected = "select\n" + @@ -1371,26 +1367,121 @@ public void test330InOidTest() throws Exception { } } + @Test + public void test330OwnerInOidTest() throws Exception { + Session session = open(); + try { + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .ownerId("1", "2").build(); + + String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " RObject o\n" + + "where\n" + + " o.ownerOid in :oid\n"; + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + @Test public void test340QueryOrgTreeFindOrgs() throws Exception { Session session = open(); try { - OrgFilter orgFilter = OrgFilter.createOrg("some oid", OrgFilter.Scope.ONE_LEVEL); - ObjectQuery objectQuery = ObjectQuery.createObjectQuery(orgFilter); - objectQuery.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); - objectQuery.setUseNewQueryInterpreter(true); + ObjectQuery query0 = ObjectQuery.createObjectQuery(orgFilter); + query0.setPaging(ObjectPaging.createPaging(null, null, F_NAME, ASCENDING)); + query0.setUseNewQueryInterpreter(true); -// ObjectQuery query1 = QueryBuilder.queryFor(OrgType.class, prismContext) -// .isDirectChildOf("some oid") -// .asc(ObjectType.F_NAME) -// .build(); + ObjectQuery query = QueryBuilder.queryFor(OrgType.class, prismContext) + .isDirectChildOf("some oid") + .asc(ObjectType.F_NAME) + .build(); + + String real = getInterpretedQuery2(session, OrgType.class, query); + + OperationResult result = new OperationResult("query org structure"); + repositoryService.searchObjects(OrgType.class, query, null, result); + + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " ROrg o\n" + + "where\n" + + " o.oid in (select ref.ownerOid from RObjectReference ref where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and ref.targetOid = :orgOid)\n" + + "order by o.name.orig asc\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test345QueryOrgAllLevels() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(OrgType.class, prismContext) + .isChildOf(new PrismReferenceValue("123")) + .asc(ObjectType.F_NAME) + .build(); + + String real = getInterpretedQuery2(session, OrgType.class, query); + + OperationResult result = new OperationResult("query org structure"); + repositoryService.searchObjects(OrgType.class, query, null, result); + + String expected = "select\n" + + " o.fullObject,\n" + + " o.stringsCount,\n" + + " o.longsCount,\n" + + " o.datesCount,\n" + + " o.referencesCount,\n" + + " o.polysCount,\n" + + " o.booleansCount\n" + + "from\n" + + " ROrg o\n" + + "where\n" + + " o.oid in (select ref.ownerOid from RObjectReference ref where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and ref.targetOid = :orgOid)\n" + + "order by o.name.orig asc\n"; + + assertEqualsIgnoreWhitespace(expected, real); + } finally { + close(session); + } + } + + @Test + public void test348QueryRoots() throws Exception { + Session session = open(); + + try { + ObjectQuery query = QueryBuilder.queryFor(OrgType.class, prismContext) + .isRoot() + .asc(ObjectType.F_NAME) + .build(); - String real = getInterpretedQuery2(session, OrgType.class, objectQuery); + String real = getInterpretedQuery2(session, OrgType.class, query); OperationResult result = new OperationResult("query org structure"); - repositoryService.searchObjects(OrgType.class, objectQuery, null, result); + repositoryService.searchObjects(OrgType.class, query, null, result); String expected = "select\n" + " o.fullObject,\n" + From bb343e610a79c93312007515e4d2b74bcf1ff0c2 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 7 Dec 2015 20:28:24 +0100 Subject: [PATCH 074/116] Schema for custom forms (adminGuiConfig) --- .../xml/ns/public/common/common-3.xsd | 102 +++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 7b06d14b5fa..451ae28f47e 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -46,7 +46,7 @@ https://wiki.evolveum.com/display/midPoint/Data+Model for more details. -

Version: 3.3

+

Version: 3.4-SNAPSHOT

Recommended namespace prefix: (default), c

@@ -7132,6 +7132,19 @@
+ + + +

+ Specifies the admin GUI configuration that should be used + for the members of this role. +

+
+ + 3.4 + +
+
@@ -8804,6 +8817,19 @@ + + + +

+ Specifies the set of default forms that are used for displaying and + editing of objects, such as User, Role, Org, ... +

+
+ + 3.4 + +
+
@@ -13497,6 +13523,80 @@ + + + + + + + + + + + Specifies the set of forms that are used for displaying and + editing of objects, such as User, Role, Org, ... + + + + 3.4 + + + + + + + + + + + Specifies form that are used for displaying and + editing of specific object type + + + + 3.4 + + + + + + + + + + + + Specifies a form using several different methods, e.g. by + specification of Java class, internal form OID, etc. + + + + 3.4 + + + + + + + Reference to midPoint form object + + + tns:FormType + + + + + + + Name of the Java class that will be used as the form implementation. + + + + + + + From b3df27799446c2b6dea6bc1bf22ddf7bbcf15385 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 8 Dec 2015 00:39:29 +0100 Subject: [PATCH 075/116] Crude breakup of sql repo impl into a set of cooperating classes. (Delete campaign does not work yet.) --- .../midpoint/prism/PrismContainerValue.java | 10 +- .../xml/ns/public/common/common-3.xsd | 4 +- .../midpoint/repo/sql/AddGetObjectTest.java | 3 + .../repo/sql/QueryInterpreter2Test.java | 24 +- .../closure/OrgClosureConcurrencyTest.java | 3 +- .../src/test/resources/basic/objects.xml | 224 +++ .../src/test/resources/logback-test.xml | 2 +- .../repo/sql/ObjectPagingAfterOid.java | 55 + .../midpoint/repo/sql/SqlBaseService.java | 22 +- .../repo/sql/SqlRepositoryConfiguration.java | 1 + .../repo/sql/SqlRepositoryServiceImpl.java | 1630 ++--------------- .../container/RAccessCertificationCase.java | 8 +- .../sql/helpers/CertificationCaseHelper.java | 4 +- .../repo/sql/helpers/ObjectRetriever.java | 828 +++++++++ .../repo/sql/helpers/ObjectUpdater.java | 545 ++++++ .../sql/{ => helpers}/OrgClosureManager.java | 46 +- .../repo/sql/helpers/SequenceHelper.java | 195 ++ .../repo/sql/helpers/TransactionHelper.java | 91 + .../repo/sql/query/QueryInterpreter.java | 3 +- .../repo/sql/query2/QueryInterpreter2.java | 2 +- 20 files changed, 2133 insertions(+), 1567 deletions(-) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/ObjectPagingAfterOid.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java rename repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/{ => helpers}/OrgClosureManager.java (97%) create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/SequenceHelper.java create mode 100644 repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/TransactionHelper.java diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java index a013bf8aabf..58727c31873 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java @@ -873,7 +873,15 @@ public void removeContainer(ItemPath itemPath) { removeItem(itemPath, PrismContainer.class); } - // Expects that "self" path is NOT present in propPath + public void removeReference(QName name) { + removeReference(new ItemPath(name)); + } + + public void removeReference(ItemPath path) { + removeItem(path, PrismReference.class); + } + + // Expects that "self" path is NOT present in propPath > void removeItem(ItemPath propPath, Class itemType) { if (items == null){ return; diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 002406951bc..207fc4e6e20 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -12154,7 +12154,7 @@ - + @@ -12435,7 +12435,7 @@ - + diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java index 3fa37040c29..8f3a8960a73 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java @@ -161,6 +161,9 @@ private void addGetCompare(File file) throws Exception { } else if (LookupTableType.class.equals(clazz)) { o = SelectorOptions.createCollection(LookupTableType.F_ROW, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); + } else if (AccessCertificationCampaignType.class.equals(clazz)) { + o = SelectorOptions.createCollection(AccessCertificationCampaignType.F_CASE, + GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); } PrismObject newObject = repositoryService.getObject(clazz, oids.get(i), o, result); LOGGER.info("Old\n{}\nnew\n{}", new Object[]{object.debugDump(3), newObject.debugDump(3)}); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java index 49eff0e5753..a7be1f6bfcf 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/QueryInterpreter2Test.java @@ -1368,7 +1368,7 @@ public void test330InOidTest() throws Exception { } @Test - public void test330OwnerInOidTest() throws Exception { + public void test335OwnerInOidTest() throws Exception { Session session = open(); try { ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) @@ -1376,17 +1376,11 @@ public void test330OwnerInOidTest() throws Exception { String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); String expected = "select\n" + - " o.fullObject,\n" + - " o.stringsCount,\n" + - " o.longsCount,\n" + - " o.datesCount,\n" + - " o.referencesCount,\n" + - " o.polysCount,\n" + - " o.booleansCount\n" + + " a.fullObject\n" + "from\n" + - " RObject o\n" + + " RAccessCertificationCase a\n" + "where\n" + - " o.ownerOid in :oid\n"; + " a.ownerOid in :ownerOid"; assertEqualsIgnoreWhitespace(expected, real); } finally { close(session); @@ -1459,8 +1453,8 @@ public void test345QueryOrgAllLevels() throws Exception { "from\n" + " ROrg o\n" + "where\n" + - " o.oid in (select ref.ownerOid from RObjectReference ref where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and ref.targetOid = :orgOid)\n" + - "order by o.name.orig asc\n"; + " o.oid in (select ref.ownerOid from RObjectReference ref where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and ref.targetOid in (select descendantOid from ROrgClosure where ancestorOid = :orgOid))\n" + + "order by o.name.orig asc"; assertEqualsIgnoreWhitespace(expected, real); } finally { @@ -1494,8 +1488,8 @@ public void test348QueryRoots() throws Exception { "from\n" + " ROrg o\n" + "where\n" + - " o.oid in (select ref.ownerOid from RObjectReference ref where ref.referenceType = com.evolveum.midpoint.repo.sql.data.common.other.RReferenceOwner.OBJECT_PARENT_ORG and ref.targetOid = :orgOid)\n" + - "order by o.name.orig asc\n"; + " o.oid in (select descendantOid from ROrgClosure group by descendantOid having count(descendantOid) = 1)\n" + + "order by o.name.orig asc"; assertEqualsIgnoreWhitespace(expected, real); } finally { @@ -2024,7 +2018,7 @@ public void test530queryUserSubstringName() throws Exception { objectQuery = ObjectQuery.createObjectQuery(substring); objectQuery.setUseNewQueryInterpreter(true); count = repositoryService.countObjects(ObjectType.class, objectQuery, result); - AssertJUnit.assertEquals(18, count); + AssertJUnit.assertEquals(19, count); } finally { close(session); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/closure/OrgClosureConcurrencyTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/closure/OrgClosureConcurrencyTest.java index 01f9823ab3c..cc3557ad76c 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/closure/OrgClosureConcurrencyTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/closure/OrgClosureConcurrencyTest.java @@ -29,7 +29,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; @@ -41,7 +40,7 @@ import java.util.List; import java.util.Set; -import static com.evolveum.midpoint.repo.sql.OrgClosureManager.Edge; +import static com.evolveum.midpoint.repo.sql.helpers.OrgClosureManager.Edge; /** * @author mederly diff --git a/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml b/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml index b63b62e4e83..d2759b9d606 100644 --- a/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml +++ b/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml @@ -1345,4 +1345,228 @@ 3 value + + + All user assignments 1 + Certifies all users' assignments. Everything is certified by the administrator. + + 2015-12-18T23:59:59.999+01:00 + http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage/handler-3 + + + 2015-12-16T23:59:59.999+01:00 + http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage-approaching/handler-3 + + + 2015-12-18T11:59:59.999+01:00 + http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage-approaching/handler-3 + + + 2015-12-04T00:37:08.885+01:00 + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + + http://midpoint.evolveum.com/xml/ns/public/certification/handlers-3#direct-assignment + + + + + 1 + Administrator's review + In this stage, the administrator has to review all the assignments of all users. + 14 + 48 + 12 + true + + + + + 2015-12-04T00:38:03.031+01:00 + inReviewStage + 1 + + 1 + Administrator's review + In this stage, the administrator has to review all the assignments of all users. + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + notDecided + 2015-12-04T01:10:20.032+01:00 + + notDecided + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + accept + 2015-12-04T01:04:06.385+01:00 + + accept + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + noResponse + 2015-12-04T01:10:08.670+01:00 + + noResponse + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + revoke + 2015-12-04T01:10:13.814+01:00 + + revoke + 1 + + + + + ri:cn + + strong + + CN + + + + + ri:sn + + strong + + SN + + + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + revoke + 2015-12-04T01:10:14.614+01:00 + + revoke + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + reduce + 2015-12-04T01:10:15.375+01:00 + + reduce + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + revoke + 2015-12-04T01:10:16.136+01:00 + + revoke + 1 + + + + false + + + diff --git a/repo/repo-sql-impl-test/src/test/resources/logback-test.xml b/repo/repo-sql-impl-test/src/test/resources/logback-test.xml index 5c9eb7a216f..51f06856ad3 100644 --- a/repo/repo-sql-impl-test/src/test/resources/logback-test.xml +++ b/repo/repo-sql-impl-test/src/test/resources/logback-test.xml @@ -35,7 +35,7 @@ - + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/ObjectPagingAfterOid.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/ObjectPagingAfterOid.java new file mode 100644 index 00000000000..5fab50e5165 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/ObjectPagingAfterOid.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql; + +import com.evolveum.midpoint.prism.query.ObjectPaging; + +/** + * @author Pavol + */ // Temporary hack. Represents special paging object that means +// "give me objects with OID greater than specified one, sorted by OID ascending". +// +// TODO: replace by using cookie that is part of the standard ObjectPaging +// (but think out all consequences, e.g. conflicts with the other use of the cookie) +public class ObjectPagingAfterOid extends ObjectPaging { + private String oidGreaterThan; + + public String getOidGreaterThan() { + return oidGreaterThan; + } + + public void setOidGreaterThan(String oidGreaterThan) { + this.oidGreaterThan = oidGreaterThan; + } + + @Override + public String toString() { + return super.toString() + ", after OID: " + oidGreaterThan; + } + + @Override + public ObjectPagingAfterOid clone() { + ObjectPagingAfterOid clone = new ObjectPagingAfterOid(); + copyTo(clone); + return clone; + } + + protected void copyTo(ObjectPagingAfterOid clone) { + super.copyTo(clone); + clone.oidGreaterThan = this.oidGreaterThan; + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlBaseService.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlBaseService.java index 9326b7f7463..86fbf42aca8 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlBaseService.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlBaseService.java @@ -75,7 +75,7 @@ public SqlPerformanceMonitor getPerformanceMonitor() { return repositoryFactory.getPerformanceMonitor(); } - protected LocalSessionFactoryBean getSessionFactoryBean() { + public LocalSessionFactoryBean getSessionFactoryBean() { return sessionFactoryBean; } @@ -202,7 +202,7 @@ private boolean isExceptionRelatedToSerialization(Exception ex) { || sqlException.getErrorCode() == 3960; // Snapshot isolation transaction aborted due to update conflict. } - protected SQLException findSqlException(Throwable ex) { + public SQLException findSqlException(Throwable ex) { while (ex != null) { if (ex instanceof SQLException) { return (SQLException) ex; @@ -222,11 +222,11 @@ private boolean exceptionContainsText(Throwable ex, String text) { return false; } - protected Session beginTransaction() { + public Session beginTransaction() { return beginTransaction(false); } - protected Session beginTransaction(boolean readOnly) { + public Session beginTransaction(boolean readOnly) { Session session = getSessionFactory().openSession(); session.beginTransaction(); @@ -256,16 +256,16 @@ public void execute(Connection connection) throws SQLException { return session; } - protected void rollbackTransaction(Session session) { + public void rollbackTransaction(Session session) { rollbackTransaction(session, null, null, false); } - protected void rollbackTransaction(Session session, Exception ex, OperationResult result, boolean fatal) { + public void rollbackTransaction(Session session, Exception ex, OperationResult result, boolean fatal) { String message = ex != null ? ex.getMessage() : "null"; rollbackTransaction(session, ex, message, result, fatal); } - protected void rollbackTransaction(Session session, Exception ex, String message, OperationResult result, + public void rollbackTransaction(Session session, Exception ex, String message, OperationResult result, boolean fatal) { if (StringUtils.isEmpty(message) && ex != null) { message = ex.getMessage(); @@ -283,7 +283,7 @@ protected void rollbackTransaction(Session session, Exception ex, String message session.getTransaction().rollback(); } - protected void cleanupSessionAndResult(Session session, OperationResult result) { + public void cleanupSessionAndResult(Session session, OperationResult result) { if (session != null && session.isOpen()) { session.close(); } @@ -293,7 +293,7 @@ protected void cleanupSessionAndResult(Session session, OperationResult result) } } - protected void handleGeneralException(Exception ex, Session session, OperationResult result) { + public void handleGeneralException(Exception ex, Session session, OperationResult result) { if (ex instanceof RuntimeException) { handleGeneralRuntimeException((RuntimeException) ex, session, result); } else { @@ -301,7 +301,7 @@ protected void handleGeneralException(Exception ex, Session session, OperationRe } } - protected void handleGeneralRuntimeException(RuntimeException ex, Session session, OperationResult result) { + public void handleGeneralRuntimeException(RuntimeException ex, Session session, OperationResult result) { LOGGER.debug("General runtime exception occurred.", ex); if (isExceptionRelatedToSerialization(ex)) { @@ -319,7 +319,7 @@ protected void handleGeneralRuntimeException(RuntimeException ex, Session sessio } } - protected void handleGeneralCheckedException(Exception ex, Session session, OperationResult result) { + public void handleGeneralCheckedException(Exception ex, Session session, OperationResult result) { LOGGER.error("General checked exception occurred.", ex); boolean fatal = !isExceptionRelatedToSerialization(ex); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java index fc195a6a195..58e6baf566e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql; import com.evolveum.midpoint.repo.api.RepositoryServiceFactoryException; +import com.evolveum.midpoint.repo.sql.helpers.OrgClosureManager; import com.evolveum.midpoint.repo.sql.util.MidPointConnectionCustomizer; import com.evolveum.midpoint.repo.sql.util.MidPointMySQLDialect; import com.evolveum.midpoint.repo.sql.util.MidPointPostgreSQLDialect; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java index 0f4c2203502..f9fb1d8da62 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryServiceImpl.java @@ -20,21 +20,11 @@ import com.evolveum.midpoint.common.crypto.CryptoUtil; import com.evolveum.midpoint.prism.ConsistencyCheckScope; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.prism.PrismReferenceDefinition; import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; -import com.evolveum.midpoint.prism.delta.ReferenceDelta; -import com.evolveum.midpoint.prism.parser.XNodeProcessorEvaluationMode; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.query.AllFilter; @@ -44,83 +34,46 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.repo.api.RepositoryService; -import com.evolveum.midpoint.repo.sql.data.common.RObject; -import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; -import com.evolveum.midpoint.repo.sql.data.common.any.RValueType; -import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; -import com.evolveum.midpoint.repo.sql.helpers.CertificationCaseHelper; -import com.evolveum.midpoint.repo.sql.helpers.LookupTableHelper; -import com.evolveum.midpoint.repo.sql.helpers.GeneralHelper; -import com.evolveum.midpoint.repo.sql.helpers.NameResolutionHelper; -import com.evolveum.midpoint.repo.sql.query.QueryEngine; -import com.evolveum.midpoint.repo.sql.query.QueryException; -import com.evolveum.midpoint.repo.sql.query.RQuery; -import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; -import com.evolveum.midpoint.repo.sql.util.ClassMapper; -import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; -import com.evolveum.midpoint.repo.sql.util.GetObjectResult; -import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; -import com.evolveum.midpoint.repo.sql.util.PrismIdentifierGenerator; -import com.evolveum.midpoint.repo.sql.util.RUtil; -import com.evolveum.midpoint.repo.sql.util.ScrollableResultsIterator; +import com.evolveum.midpoint.repo.sql.helpers.ObjectRetriever; +import com.evolveum.midpoint.repo.sql.helpers.ObjectUpdater; +import com.evolveum.midpoint.repo.sql.helpers.OrgClosureManager; +import com.evolveum.midpoint.repo.sql.helpers.SequenceHelper; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.LabeledString; import com.evolveum.midpoint.schema.RepositoryDiag; import com.evolveum.midpoint.schema.ResultHandler; -import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.SearchResultMetadata; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; -import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; -import org.hibernate.Criteria; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.Query; -import org.hibernate.SQLQuery; -import org.hibernate.ScrollMode; -import org.hibernate.ScrollableResults; import org.hibernate.Session; -import org.hibernate.criterion.Restrictions; -import org.hibernate.exception.ConstraintViolationException; import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.jdbc.Work; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; -import java.lang.reflect.Method; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; -import java.util.Iterator; import java.util.List; import java.util.Properties; @@ -136,7 +89,7 @@ public class SqlRepositoryServiceImpl extends SqlBaseService implements Reposito private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(PERFORMANCE_LOG_NAME); - private static final int MAX_CONSTRAINT_NAME_LENGTH = 40; + public static final int MAX_CONSTRAINT_NAME_LENGTH = 40; private static final String IMPLEMENTATION_SHORT_NAME = "SQL"; private static final String IMPLEMENTATION_DESCRIPTION = "Implementation that stores data in generic relational" + " (SQL) databases. It is using ORM (hibernate) on top of JDBC to access the database."; @@ -147,17 +100,15 @@ public class SqlRepositoryServiceImpl extends SqlBaseService implements Reposito private static final String DETAILS_HIBERNATE_HBM_2_DDL = "hibernateHbm2ddl"; @Autowired - private GeneralHelper generalHelper; + private SequenceHelper sequenceHelper; @Autowired - private LookupTableHelper lookupTableHelper; + private ObjectRetriever objectRetriever; @Autowired - private CertificationCaseHelper caseHelper; + private ObjectUpdater objectUpdater; @Autowired - private NameResolutionHelper nameResolutionHelper; - private OrgClosureManager closureManager; public SqlRepositoryServiceImpl(SqlRepositoryFactory repositoryFactory) { @@ -166,99 +117,9 @@ public SqlRepositoryServiceImpl(SqlRepositoryFactory repositoryFactory) { // public because of testing public OrgClosureManager getClosureManager() { - if (closureManager == null) { - closureManager = new OrgClosureManager(getConfiguration()); - } return closureManager; } - private PrismObject getObject(Session session, Class type, String oid, - Collection> options, - boolean lockForUpdate) - throws ObjectNotFoundException, SchemaException, DtoTranslationException, QueryException { - - boolean lockedForUpdateViaHibernate = false; - boolean lockedForUpdateViaSql = false; - - LockOptions lockOptions = new LockOptions(); - //todo fix lock for update!!!!! - if (lockForUpdate) { - if (getConfiguration().isLockForUpdateViaHibernate()) { - lockOptions.setLockMode(LockMode.PESSIMISTIC_WRITE); - lockedForUpdateViaHibernate = true; - } else if (getConfiguration().isLockForUpdateViaSql()) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Trying to lock object " + oid + " for update (via SQL)"); - } - long time = System.currentTimeMillis(); - SQLQuery q = session.createSQLQuery("select oid from m_object where oid = ? for update"); - q.setString(0, oid); - Object result = q.uniqueResult(); - if (result == null) { - return throwObjectNotFoundException(type, oid); - } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Locked via SQL (in " + (System.currentTimeMillis() - time) + " ms)"); - } - lockedForUpdateViaSql = true; - } - } - - if (LOGGER.isTraceEnabled()) { - if (lockedForUpdateViaHibernate) { - LOGGER.trace("Getting object " + oid + " with locking for update (via hibernate)"); - } else if (lockedForUpdateViaSql) { - LOGGER.trace("Getting object " + oid + ", already locked for update (via SQL)"); - } else { - LOGGER.trace("Getting object " + oid + " without locking for update"); - } - } - - GetObjectResult fullObject = null; - if (!lockForUpdate) { - Query query = session.getNamedQuery("get.object"); - query.setString("oid", oid); - query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); - query.setLockOptions(lockOptions); - - fullObject = (GetObjectResult) query.uniqueResult(); - } else { - // we're doing update after this get, therefore we load full object right now - // (it would be loaded during merge anyway) - // this just loads object to hibernate session, probably will be removed later. Merge after this get - // will be faster. Read and use object only from fullObject column. - // todo remove this later [lazyman] - Criteria criteria = session.createCriteria(ClassMapper.getHQLTypeClass(type)); - criteria.add(Restrictions.eq("oid", oid)); - - criteria.setLockMode(lockOptions.getLockMode()); - RObject obj = (RObject) criteria.uniqueResult(); - - if (obj != null) { - obj.toJAXB(getPrismContext(), null).asPrismObject(); - fullObject = new GetObjectResult(obj.getFullObject(), obj.getStringsCount(), obj.getLongsCount(), - obj.getDatesCount(), obj.getReferencesCount(), obj.getPolysCount(), obj.getBooleansCount()); - } - } - - LOGGER.trace("Got it."); - if (fullObject == null) { - throwObjectNotFoundException(type, oid); - } - - - LOGGER.trace("Transforming data to JAXB type."); - PrismObject prismObject = updateLoadedObject(fullObject, type, options, session); - validateObjectType(prismObject, type); - - return prismObject; - } - - private PrismObject throwObjectNotFoundException(Class type, String oid) - throws ObjectNotFoundException { - throw new ObjectNotFoundException("Object of type '" + type.getSimpleName() + "' with oid '" + oid - + "' was not found.", null, oid); - } @Override public PrismObject getObject(Class type, String oid, @@ -284,7 +145,7 @@ public PrismObject getObject(Class type, String oid try { while (true) { try { - return getObjectAttempt(type, oid, options, subResult); + return objectRetriever.getObjectAttempt(type, oid, options, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(oid, operation, attempt, ex, subResult); pm.registerOperationNewTrial(opHandle, attempt); @@ -295,45 +156,6 @@ public PrismObject getObject(Class type, String oid } } - private PrismObject getObjectAttempt(Class type, String oid, - Collection> options, - OperationResult result) - throws ObjectNotFoundException, SchemaException { - LOGGER_PERFORMANCE.debug("> get object {}, oid={}", type.getSimpleName(), oid); - PrismObject objectType = null; - - Session session = null; - try { - session = beginReadOnlyTransaction(); - - objectType = getObject(session, type, oid, options, false); - - session.getTransaction().commit(); - } catch (ObjectNotFoundException ex) { - GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); - rollbackTransaction(session, ex, result, !GetOperationOptions.isAllowNotFound(rootOptions)); - throw ex; - } catch (SchemaException ex) { - rollbackTransaction(session, ex, "Schema error while getting object with oid: " - + oid + ". Reason: " + ex.getMessage(), result, true); - throw ex; - } catch (QueryException | DtoTranslationException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Get object:\n{}", new Object[]{(objectType != null ? objectType.debugDump(3) : null)}); - } - - return objectType; - } - - private Session beginReadOnlyTransaction() { - return beginTransaction(getConfiguration().isUseReadOnlyTransactions()); - } - @Override public PrismObject searchShadowOwner(String shadowOid, Collection> options, OperationResult result) { Validate.notEmpty(shadowOid, "Oid must not be null or empty."); @@ -349,52 +171,13 @@ public PrismObject searchShadowOwner(String shadowOid, while (true) { try { - return searchShadowOwnerAttempt(shadowOid, options, subResult); + return objectRetriever.searchShadowOwnerAttempt(shadowOid, options, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(shadowOid, operation, attempt, ex, subResult); } } } - private PrismObject searchShadowOwnerAttempt(String shadowOid, Collection> options, OperationResult result) { - LOGGER_PERFORMANCE.debug("> search shadow owner for oid={}", shadowOid); - PrismObject owner = null; - Session session = null; - try { - session = beginReadOnlyTransaction(); - LOGGER.trace("Selecting account shadow owner for account {}.", new Object[]{shadowOid}); - Query query = session.getNamedQuery("searchShadowOwner.getOwner"); - query.setString("oid", shadowOid); - query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); - - List focuses = query.list(); - LOGGER.trace("Found {} focuses, transforming data to JAXB types.", - new Object[]{(focuses != null ? focuses.size() : 0)}); - - if (focuses == null || focuses.isEmpty()) { - // account shadow owner was not found - return null; - } - - if (focuses.size() > 1) { - LOGGER.warn("Found {} owners for shadow oid {}, returning first owner.", - new Object[]{focuses.size(), shadowOid}); - } - - GetObjectResult focus = focuses.get(0); - owner = updateLoadedObject(focus, (Class) FocusType.class, options, session); - - session.getTransaction().commit(); - - } catch (SchemaException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - return owner; - } - @Override @Deprecated public PrismObject listAccountShadowOwner(String accountOid, OperationResult result) @@ -412,444 +195,13 @@ public PrismObject listAccountShadowOwner(String accountOid, Operation while (true) { try { - return listAccountShadowOwnerAttempt(accountOid, subResult); + return objectRetriever.listAccountShadowOwnerAttempt(accountOid, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(accountOid, operation, attempt, ex, subResult); } } } - private PrismObject listAccountShadowOwnerAttempt(String accountOid, OperationResult result) - throws ObjectNotFoundException { - LOGGER_PERFORMANCE.debug("> list account shadow owner oid={}", accountOid); - PrismObject userType = null; - Session session = null; - try { - session = beginReadOnlyTransaction(); - Query query = session.getNamedQuery("listAccountShadowOwner.getUser"); - query.setString("oid", accountOid); - query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); - - List users = query.list(); - LOGGER.trace("Found {} users, transforming data to JAXB types.", - new Object[]{(users != null ? users.size() : 0)}); - - if (users == null || users.isEmpty()) { - // account shadow owner was not found - return null; - } - - if (users.size() > 1) { - LOGGER.warn("Found {} users for account oid {}, returning first user. [interface change needed]", - new Object[]{users.size(), accountOid}); - } - - GetObjectResult user = users.get(0); - userType = updateLoadedObject(user, UserType.class, null, session); - - session.getTransaction().commit(); - } catch (SchemaException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - return userType; - } - - private void validateName(PrismObject object) throws SchemaException { - PrismProperty name = object.findProperty(ObjectType.F_NAME); - if (name == null || ((PolyString) name.getRealValue()).isEmpty()) { - throw new SchemaException("Attempt to add object without name."); - } - } - - @Override - public String addObject(PrismObject object, RepoAddOptions options, OperationResult result) - throws ObjectAlreadyExistsException, SchemaException { - Validate.notNull(object, "Object must not be null."); - validateName(object); - Validate.notNull(result, "Operation result must not be null."); - - if (options == null) { - options = new RepoAddOptions(); - } - - LOGGER.debug("Adding object type '{}', overwrite={}, allowUnencryptedValues={}", - new Object[]{object.getCompileTimeClass().getSimpleName(), options.isOverwrite(), - options.isAllowUnencryptedValues()} - ); - - if (InternalsConfig.encryptionChecks && !RepoAddOptions.isAllowUnencryptedValues(options)) { - CryptoUtil.checkEncrypted(object); - } - - if (InternalsConfig.consistencyChecks) { - object.checkConsistence(ConsistencyCheckScope.THOROUGH); - } else { - object.checkConsistence(ConsistencyCheckScope.MANDATORY_CHECKS_ONLY); - } - - if (LOGGER.isTraceEnabled()) { - // Explicitly log name - PolyStringType namePolyType = object.asObjectable().getName(); - LOGGER.trace("NAME: {} - {}", namePolyType.getOrig(), namePolyType.getNorm()); - } - - OperationResult subResult = result.createSubresult(ADD_OBJECT); - subResult.addParam("object", object); - subResult.addParam("options", options); - - final String operation = "adding"; - int attempt = 1; - - String oid = object.getOid(); - while (true) { - try { - return addObjectAttempt(object, options, subResult); - } catch (RuntimeException ex) { - attempt = logOperationAttempt(oid, operation, attempt, ex, subResult); - } - } - } - - private String addObjectAttempt(PrismObject object, RepoAddOptions options, - OperationResult result) - throws ObjectAlreadyExistsException, SchemaException { - LOGGER_PERFORMANCE.debug("> add object {}, oid={}, overwrite={}", - new Object[]{object.getCompileTimeClass().getSimpleName(), object.getOid(), options.isOverwrite()}); - String oid = null; - Session session = null; - OrgClosureManager.Context closureContext = null; - // it is needed to keep the original oid for example for import options. if we do not keep it - // and it was null it can bring some error because the oid is set when the object contains orgRef - // or it is org. and by the import we do not know it so it will be trying to delete non-existing object - String originalOid = object.getOid(); - try { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Object\n{}", new Object[]{object.debugDump()}); - } - - LOGGER.trace("Translating JAXB to data type."); - PrismIdentifierGenerator.Operation operation = options.isOverwrite() ? - PrismIdentifierGenerator.Operation.ADD_WITH_OVERWRITE : - PrismIdentifierGenerator.Operation.ADD; - - RObject rObject = createDataObjectFromJAXB(object, operation); - - session = beginTransaction(); - - closureContext = getClosureManager().onBeginTransactionAdd(session, object, options.isOverwrite()); - - if (options.isOverwrite()) { - oid = overwriteAddObjectAttempt(object, rObject, originalOid, session, closureContext); - } else { - oid = nonOverwriteAddObjectAttempt(object, rObject, originalOid, session, closureContext); - } - session.getTransaction().commit(); - - LOGGER.trace("Saved object '{}' with oid '{}'", new Object[]{ - object.getCompileTimeClass().getSimpleName(), oid}); - - object.setOid(oid); - } catch (ConstraintViolationException ex) { - handleConstraintViolationException(session, ex, result); - rollbackTransaction(session, ex, result, true); - - LOGGER.debug("Constraint violation occurred (will be rethrown as ObjectAlreadyExistsException).", ex); - // we don't know if it's only name uniqueness violation, or something else, - // therefore we're throwing it always as ObjectAlreadyExistsException revert - // to the original oid and prevent of unexpected behaviour (e.g. by import with overwrite option) - if (StringUtils.isEmpty(originalOid)) { - object.setOid(null); - } - String constraintName = ex.getConstraintName(); - // Breaker to avoid long unreadable messages - if (constraintName != null && constraintName.length() > MAX_CONSTRAINT_NAME_LENGTH) { - constraintName = null; - } - throw new ObjectAlreadyExistsException("Conflicting object already exists" - + (constraintName == null ? "" : " (violated constraint '" + constraintName + "')"), ex); - } catch (ObjectAlreadyExistsException | SchemaException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (DtoTranslationException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupClosureAndSessionAndResult(closureContext, session, result); - } - - return oid; - } - - private String overwriteAddObjectAttempt(PrismObject object, RObject rObject, - String originalOid, Session session, OrgClosureManager.Context closureContext) - throws ObjectAlreadyExistsException, SchemaException, DtoTranslationException { - - PrismObject oldObject = null; - - //check if object already exists, find differences and increment version if necessary - Collection modifications = null; - if (originalOid != null) { - try { - oldObject = getObject(session, object.getCompileTimeClass(), originalOid, null, true); - ObjectDelta delta = object.diff(oldObject); - modifications = delta.getModifications(); - - //we found existing object which will be overwritten, therefore we increment version - Integer version = RUtil.getIntegerFromString(oldObject.getVersion()); - version = (version == null) ? 0 : ++version; - - rObject.setVersion(version); - } catch (QueryException ex) { - handleGeneralCheckedException(ex, session, null); - } catch (ObjectNotFoundException ex) { - //it's ok that object was not found, therefore we won't be overwriting it - } - } - - updateFullObject(rObject, object); - RObject merged = (RObject) session.merge(rObject); - lookupTableHelper.addLookupTableRows(session, rObject, modifications != null); - caseHelper.addCertificationCampaignCases(session, rObject, modifications != null); - - if (getClosureManager().isEnabled()) { - OrgClosureManager.Operation operation; - if (modifications == null) { - operation = OrgClosureManager.Operation.ADD; - modifications = createAddParentRefDelta(object); - } else { - operation = OrgClosureManager.Operation.MODIFY; - } - getClosureManager().updateOrgClosure(oldObject, modifications, session, merged.getOid(), object.getCompileTimeClass(), - operation, closureContext); - } - return merged.getOid(); - } - - private void updateFullObject(RObject object, PrismObject savedObject) - throws DtoTranslationException, SchemaException { - LOGGER.debug("Updating full object xml column start."); - savedObject.setVersion(Integer.toString(object.getVersion())); - - if (FocusType.class.isAssignableFrom(savedObject.getCompileTimeClass())) { - savedObject.removeProperty(FocusType.F_JPEG_PHOTO); - } else if (LookupTableType.class.equals(savedObject.getCompileTimeClass())) { - PrismContainer table = savedObject.findContainer(LookupTableType.F_ROW); - savedObject.remove(table); - } else if (AccessCertificationCampaignType.class.equals(savedObject.getCompileTimeClass())) { - PrismContainer caseContainer = savedObject.findContainer(AccessCertificationCampaignType.F_CASE); - savedObject.remove(caseContainer); - } - - String xml = getPrismContext().serializeObjectToString(savedObject, PrismContext.LANG_XML); - byte[] fullObject = RUtil.getByteArrayFromXml(xml, getConfiguration().isUseZip()); - - if (LOGGER.isTraceEnabled()) LOGGER.trace("Storing full object\n{}", xml); - - object.setFullObject(fullObject); - - LOGGER.debug("Updating full object xml column finish."); - } - - private String nonOverwriteAddObjectAttempt(PrismObject object, RObject rObject, - String originalOid, Session session, OrgClosureManager.Context closureContext) - throws ObjectAlreadyExistsException, SchemaException, DtoTranslationException { - - // check name uniqueness (by type) - if (StringUtils.isNotEmpty(originalOid)) { - LOGGER.trace("Checking oid uniqueness."); - //todo improve this table name bullshit - Class hqlType = ClassMapper.getHQLTypeClass(object.getCompileTimeClass()); - SQLQuery query = session.createSQLQuery("select count(*) from " + RUtil.getTableName(hqlType) - + " where oid=:oid"); - query.setString("oid", object.getOid()); - - Number count = (Number) query.uniqueResult(); - if (count != null && count.longValue() > 0) { - throw new ObjectAlreadyExistsException("Object '" + object.getCompileTimeClass().getSimpleName() - + "' with oid '" + object.getOid() + "' already exists."); - } - } - - updateFullObject(rObject, object); - - LOGGER.trace("Saving object (non overwrite)."); - String oid = (String) session.save(rObject); - lookupTableHelper.addLookupTableRows(session, rObject, false); - caseHelper.addCertificationCampaignCases(session, rObject, false); - - if (getClosureManager().isEnabled()) { - Collection modifications = createAddParentRefDelta(object); - getClosureManager().updateOrgClosure(null, modifications, session, oid, object.getCompileTimeClass(), - OrgClosureManager.Operation.ADD, closureContext); - } - - return oid; - } - - @Override - public void deleteObject(Class type, String oid, OperationResult result) - throws ObjectNotFoundException { - Validate.notNull(type, "Object type must not be null."); - Validate.notEmpty(oid, "Oid must not be null or empty."); - Validate.notNull(result, "Operation result must not be null."); - - LOGGER.debug("Deleting object type '{}' with oid '{}'", new Object[]{type.getSimpleName(), oid}); - - final String operation = "deleting"; - int attempt = 1; - - OperationResult subResult = result.createSubresult(DELETE_OBJECT); - subResult.addParam("type", type.getName()); - subResult.addParam("oid", oid); - - SqlPerformanceMonitor pm = getPerformanceMonitor(); - long opHandle = pm.registerOperationStart("deleteObject"); - - try { - while (true) { - try { - deleteObjectAttempt(type, oid, subResult); - return; - } catch (RuntimeException ex) { - attempt = logOperationAttempt(oid, operation, attempt, ex, subResult); - pm.registerOperationNewTrial(opHandle, attempt); - } - } - } finally { - pm.registerOperationFinish(opHandle, attempt); - } - } - - private List createAddParentRefDelta(PrismObject object) { - PrismReference parentOrgRef = object.findReference(ObjectType.F_PARENT_ORG_REF); - if (parentOrgRef == null || parentOrgRef.isEmpty()) { - return new ArrayList<>(); - } - - PrismObjectDefinition def = object.getDefinition(); - ReferenceDelta delta = ReferenceDelta.createModificationAdd(new ItemPath(ObjectType.F_PARENT_ORG_REF), - def, parentOrgRef.getClonedValues()); - - return Arrays.asList(delta); - } - - private void deleteObjectAttempt(Class type, String oid, OperationResult result) - throws ObjectNotFoundException { - LOGGER_PERFORMANCE.debug("> delete object {}, oid={}", new Object[]{type.getSimpleName(), oid}); - Session session = null; - OrgClosureManager.Context closureContext = null; - try { - session = beginTransaction(); - - closureContext = getClosureManager().onBeginTransactionDelete(session, type, oid); - - Criteria query = session.createCriteria(ClassMapper.getHQLTypeClass(type)); - query.add(Restrictions.eq("oid", oid)); - RObject object = (RObject) query.uniqueResult(); - if (object == null) { - throw new ObjectNotFoundException("Object of type '" + type.getSimpleName() + "' with oid '" + oid - + "' was not found.", null, oid); - } - - getClosureManager().updateOrgClosure(null, null, session, oid, type, OrgClosureManager.Operation.DELETE, closureContext); - - session.delete(object); - if (LookupTableType.class.equals(type)) { - lookupTableHelper.deleteLookupTableRows(session, oid); - } - if (AccessCertificationCampaignType.class.equals(type)) { - caseHelper.deleteCertificationCampaignCases(session, oid); - } - - session.getTransaction().commit(); - } catch (ObjectNotFoundException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupClosureAndSessionAndResult(closureContext, session, result); - } - } - - @Override - public int countObjects(Class type, ObjectQuery query, OperationResult result) { - Validate.notNull(type, "Object type must not be null."); - Validate.notNull(result, "Operation result must not be null."); - - LOGGER.debug("Counting objects of type '{}', query (on trace level).", new Object[]{type.getSimpleName()}); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Full query\n{}", new Object[]{(query == null ? "undefined" : query.debugDump())}); - } - - OperationResult subResult = result.createMinorSubresult(COUNT_OBJECTS); - subResult.addParam("type", type.getName()); - subResult.addParam("query", query); - - if (query != null) { - ObjectFilter filter = query.getFilter(); - filter = ObjectQueryUtil.simplify(filter); - if (filter instanceof NoneFilter) { - subResult.recordSuccess(); - return 0; - } - query = query.cloneEmpty(); - query.setFilter(filter); - } - - final String operation = "counting"; - int attempt = 1; - - while (true) { - try { - return countObjectsAttempt(type, query, subResult); - } catch (RuntimeException ex) { - attempt = logOperationAttempt(null, operation, attempt, ex, subResult); - } - } - } - - private int countObjectsAttempt(Class type, ObjectQuery query, OperationResult result) { - LOGGER_PERFORMANCE.debug("> count objects {}", new Object[]{type.getSimpleName()}); - - int count = 0; - - Session session = null; - try { - Class hqlType = ClassMapper.getHQLTypeClass(type); - - session = beginReadOnlyTransaction(); - Number longCount; - if (query == null || query.getFilter() == null) { - // this is 5x faster than count with 3 inner joins, it can probably improved also for queries which - // filters uses only properties from concrete entities like RUser, RRole by improving interpreter [lazyman] - SQLQuery sqlQuery = session.createSQLQuery("SELECT COUNT(*) FROM " + RUtil.getTableName(hqlType)); - longCount = (Number) sqlQuery.uniqueResult(); - } else { - RQuery rQuery; - if (isUseNewQueryInterpreter(query)) { - QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); - rQuery = engine.interpret(query, type, null, true, session); - } else { - QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); - rQuery = engine.interpret(query, type, null, true, session); - } - - longCount = (Number) rQuery.uniqueResult(); - } - LOGGER.trace("Found {} objects.", longCount); - count = longCount != null ? longCount.intValue() : 0; - } catch (QueryException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - return count; - } - @Override public SearchResultList> searchObjects(Class type, ObjectQuery query, Collection> options, @@ -871,13 +223,13 @@ public SearchResultList> searchObjects(Cla subResult.recordSuccess(); return new SearchResultList(new ArrayList>(0)); } else if (filter instanceof AllFilter){ - query = query.cloneEmpty(); - query.setFilter(null); + query = query.cloneEmpty(); + query.setFilter(null); } else { - query = query.cloneEmpty(); - query.setFilter(filter); + query = query.cloneEmpty(); + query.setFilter(filter); } - + } SqlPerformanceMonitor pm = getPerformanceMonitor(); @@ -888,7 +240,7 @@ public SearchResultList> searchObjects(Cla try { while (true) { try { - return searchObjectsAttempt(type, query, options, subResult); + return objectRetriever.searchObjectsAttempt(type, query, options, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(null, operation, attempt, ex, subResult); pm.registerOperationNewTrial(opHandle, attempt); @@ -935,7 +287,7 @@ public SearchResultList searchContainers(Class t try { while (true) { try { - return searchContainersAttempt(type, query, options, result); + return objectRetriever.searchContainersAttempt(type, query, options, result); } catch (RuntimeException ex) { attempt = logOperationAttempt(null, operation, attempt, ex, result); pm.registerOperationNewTrial(opHandle, attempt); @@ -968,171 +320,129 @@ private void logSearchInputParameters(Class type, ObjectQuery query, bool } } - private SearchResultList> searchObjectsAttempt(Class type, ObjectQuery query, - Collection> options, - OperationResult result) throws SchemaException { - LOGGER_PERFORMANCE.debug("> search objects {}", new Object[]{type.getSimpleName()}); - List> list = new ArrayList<>(); - Session session = null; - try { - session = beginReadOnlyTransaction(); - RQuery rQuery; - - if (isUseNewQueryInterpreter(query)) { - QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); - rQuery = engine.interpret(query, type, options, false, session); - } else { - QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); - rQuery = engine.interpret(query, type, options, false, session); - } - - List objects = rQuery.list(); - LOGGER.trace("Found {} objects, translating to JAXB.", new Object[]{(objects != null ? objects.size() : 0)}); - - for (GetObjectResult object : objects) { - PrismObject prismObject = updateLoadedObject(object, type, options, session); - list.add(prismObject); - } + @Override + public String addObject(PrismObject object, RepoAddOptions options, OperationResult result) + throws ObjectAlreadyExistsException, SchemaException { + Validate.notNull(object, "Object must not be null."); + validateName(object); + Validate.notNull(result, "Operation result must not be null."); - session.getTransaction().commit(); - } catch (QueryException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); + if (options == null) { + options = new RepoAddOptions(); } - return new SearchResultList>(list); - } + LOGGER.debug("Adding object type '{}', overwrite={}, allowUnencryptedValues={}", + new Object[]{object.getCompileTimeClass().getSimpleName(), options.isOverwrite(), + options.isAllowUnencryptedValues()} + ); - private SearchResultList searchContainersAttempt(Class type, ObjectQuery query, - Collection> options, - OperationResult result) throws SchemaException { + if (InternalsConfig.encryptionChecks && !RepoAddOptions.isAllowUnencryptedValues(options)) { + CryptoUtil.checkEncrypted(object); + } - if (!(AccessCertificationCaseType.class.equals(type))) { - throw new UnsupportedOperationException("Only AccessCertificationCaseType is supported here now."); + if (InternalsConfig.consistencyChecks) { + object.checkConsistence(ConsistencyCheckScope.THOROUGH); + } else { + object.checkConsistence(ConsistencyCheckScope.MANDATORY_CHECKS_ONLY); } - LOGGER_PERFORMANCE.debug("> search containers {}", new Object[]{type.getSimpleName()}); - List list = new ArrayList<>(); - Session session = null; - try { - session = beginReadOnlyTransaction(); + if (LOGGER.isTraceEnabled()) { + // Explicitly log name + PolyStringType namePolyType = object.asObjectable().getName(); + LOGGER.trace("NAME: {} - {}", namePolyType.getOrig(), namePolyType.getNorm()); + } - QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); - RQuery rQuery = engine.interpret(query, type, options, false, session); + OperationResult subResult = result.createSubresult(ADD_OBJECT); + subResult.addParam("object", object); + subResult.addParam("options", options); - List items = rQuery.list(); - LOGGER.trace("Found {} items, translating to JAXB.", items.size()); + final String operation = "adding"; + int attempt = 1; - for (GetObjectResult item : items) { - C value = (C) caseHelper.updateLoadedCertificationCase(item, options, session); - list.add(value); + String oid = object.getOid(); + while (true) { + try { + return objectUpdater.addObjectAttempt(object, options, subResult); + } catch (RuntimeException ex) { + attempt = logOperationAttempt(oid, operation, attempt, ex, subResult); } - - session.getTransaction().commit(); - } catch (QueryException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); } + } - return new SearchResultList(list); + private void validateName(PrismObject object) throws SchemaException { + PrismProperty name = object.findProperty(ObjectType.F_NAME); + if (name == null || ((PolyString) name.getRealValue()).isEmpty()) { + throw new SchemaException("Attempt to add object without name."); + } } - /** - * This method provides object parsing from String and validation. - */ - private PrismObject updateLoadedObject(GetObjectResult result, Class type, - Collection> options, - Session session) throws SchemaException { + @Override + public void deleteObject(Class type, String oid, OperationResult result) + throws ObjectNotFoundException { + Validate.notNull(type, "Object type must not be null."); + Validate.notEmpty(oid, "Oid must not be null or empty."); + Validate.notNull(result, "Operation result must not be null."); - String xml = RUtil.getXmlFromByteArray(result.getFullObject(), getConfiguration().isUseZip()); - PrismObject prismObject; - try { - // "Postel mode": be tolerant what you read. We need this to tolerate (custom) schema changes - prismObject = getPrismContext().parseObject(xml, XNodeProcessorEvaluationMode.COMPAT); - } catch (SchemaException e) { - LOGGER.debug("Couldn't parse object because of schema exception ({}):\nObject: {}", e, xml); - throw e; - } catch (RuntimeException e) { - LOGGER.debug("Couldn't parse object because of unexpected exception ({}):\nObject: {}", e, xml); - throw e; - } + LOGGER.debug("Deleting object type '{}' with oid '{}'", new Object[]{type.getSimpleName(), oid}); - if (FocusType.class.isAssignableFrom(prismObject.getCompileTimeClass())) { - if (SelectorOptions.hasToLoadPath(FocusType.F_JPEG_PHOTO, options)) { - //todo improve, use user.hasPhoto flag and take options into account [lazyman] - //this is called only when options contains INCLUDE user/jpegPhoto - Query query = session.getNamedQuery("get.focusPhoto"); - query.setString("oid", prismObject.getOid()); - byte[] photo = (byte[]) query.uniqueResult(); - if (photo != null) { - PrismProperty property = prismObject.findOrCreateProperty(FocusType.F_JPEG_PHOTO); - property.setRealValue(photo); - } - } - } else if (ShadowType.class.equals(prismObject.getCompileTimeClass())) { - //we store it because provisioning now sends it to repo, but it should be transient - prismObject.removeContainer(ShadowType.F_ASSOCIATION); + final String operation = "deleting"; + int attempt = 1; - LOGGER.debug("Loading definitions for shadow attributes."); + OperationResult subResult = result.createSubresult(DELETE_OBJECT); + subResult.addParam("type", type.getName()); + subResult.addParam("oid", oid); - Short[] counts = result.getCountProjection(); - Class[] classes = GetObjectResult.EXT_COUNT_CLASSES; + SqlPerformanceMonitor pm = getPerformanceMonitor(); + long opHandle = pm.registerOperationStart("deleteObject"); - for (int i = 0; i < classes.length; i++) { - if (counts[i] == null || counts[i] == 0) { - continue; + try { + while (true) { + try { + objectUpdater.deleteObjectAttempt(type, oid, subResult); + return; + } catch (RuntimeException ex) { + attempt = logOperationAttempt(oid, operation, attempt, ex, subResult); + pm.registerOperationNewTrial(opHandle, attempt); } - - applyShadowAttributeDefinitions(classes[i], prismObject, session); } - LOGGER.debug("Definitions for attributes loaded. Counts: {}", Arrays.toString(counts)); - } else if (LookupTableType.class.equals(prismObject.getCompileTimeClass())) { - lookupTableHelper.updateLoadedLookupTable(prismObject, options, session); - } else if (AccessCertificationCampaignType.class.equals(prismObject.getCompileTimeClass())) { - caseHelper.updateLoadedCampaign(prismObject, options, session); + } finally { + pm.registerOperationFinish(opHandle, attempt); } - - nameResolutionHelper.resolveNamesIfRequested(session, prismObject.getValue(), options); - validateObjectType(prismObject, type); - - return prismObject; } + @Override + public int countObjects(Class type, ObjectQuery query, OperationResult result) { + Validate.notNull(type, "Object type must not be null."); + Validate.notNull(result, "Operation result must not be null."); - private void applyShadowAttributeDefinitions(Class anyValueType, - PrismObject object, Session session) throws SchemaException { - - PrismContainer attributes = object.findContainer(ShadowType.F_ATTRIBUTES); + LOGGER.debug("Counting objects of type '{}', query (on trace level).", new Object[]{type.getSimpleName()}); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Full query\n{}", new Object[]{(query == null ? "undefined" : query.debugDump())}); + } - Query query = session.getNamedQuery("getDefinition." + anyValueType.getSimpleName()); - query.setParameter("oid", object.getOid()); - query.setParameter("ownerType", RObjectExtensionType.ATTRIBUTES); + OperationResult subResult = result.createMinorSubresult(COUNT_OBJECTS); + subResult.addParam("type", type.getName()); + subResult.addParam("query", query); - List values = query.list(); - if (values == null || values.isEmpty()) { - return; + if (query != null) { + ObjectFilter filter = query.getFilter(); + filter = ObjectQueryUtil.simplify(filter); + if (filter instanceof NoneFilter) { + subResult.recordSuccess(); + return 0; + } + query = query.cloneEmpty(); + query.setFilter(filter); } - for (Object[] value : values) { - QName name = RUtil.stringToQName((String) value[0]); - QName type = RUtil.stringToQName((String) value[1]); - Item item = attributes.findItem(name); - - // A switch statement used to be here - // but that caused strange trouble with OpenJDK. This if-then-else works. - if (item.getDefinition() == null) { - RValueType rValType = (RValueType) value[2]; - if (rValType == RValueType.PROPERTY) { - PrismPropertyDefinition def = new PrismPropertyDefinition(name, type, object.getPrismContext()); - item.applyDefinition(def, true); - } else if (rValType == RValueType.REFERENCE) { - PrismReferenceDefinition def = new PrismReferenceDefinition(name, type, object.getPrismContext()); - item.applyDefinition(def, true); - } else { - throw new UnsupportedOperationException("Unsupported value type " + rValType); - } + final String operation = "counting"; + int attempt = 1; + + while (true) { + try { + return objectRetriever.countObjectsAttempt(type, query, subResult); + } catch (RuntimeException ex) { + attempt = logOperationAttempt(null, operation, attempt, ex, subResult); } } } @@ -1193,7 +503,7 @@ public void modifyObject(Class type, String oid, try { while (true) { try { - modifyObjectAttempt(type, oid, modifications, subResult); + objectUpdater.modifyObjectAttempt(type, oid, modifications, subResult); return; } catch (RuntimeException ex) { attempt = logOperationAttempt(oid, operation, attempt, ex, subResult); @@ -1206,183 +516,6 @@ public void modifyObject(Class type, String oid, } - private void modifyObjectAttempt(Class type, String oid, - Collection modifications, - OperationResult result) throws ObjectNotFoundException, - SchemaException, ObjectAlreadyExistsException, SerializationRelatedException { - - // shallow clone - because some methods, e.g. filterLookupTableModifications manipulate this collection - modifications = new ArrayList<>(modifications); - - LOGGER.debug("Modifying object '{}' with oid '{}'.", new Object[]{type.getSimpleName(), oid}); - LOGGER_PERFORMANCE.debug("> modify object {}, oid={}, modifications={}", - new Object[]{type.getSimpleName(), oid, modifications}); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Modifications:\n{}", new Object[]{DebugUtil.debugDump(modifications)}); - } - - Session session = null; - OrgClosureManager.Context closureContext = null; - try { - session = beginTransaction(); - - closureContext = getClosureManager().onBeginTransactionModify(session, type, oid, modifications); - - Collection lookupTableModifications = lookupTableHelper.filterLookupTableModifications(type, modifications); - Collection campaignCaseModifications = caseHelper.filterCampaignCaseModifications(type, modifications); - - // JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big. - // Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo - // association. However, this leads to a strange problem when merging in-memory RFocus object with the database state: - // If in-memory RFocus object has no photo associated (because of lazy loading), then the associated RFocusPhoto is deleted. - // - // To prevent this behavior, we've set orphanRemoval to false. Fortunately, the remove operation on RFocus - // seems to be still cascaded to RFocusPhoto. What we have to implement ourselves, however, is removal of RFocusPhoto - // _without_ removing of RFocus. In order to know whether the photo has to be removed, we have to retrieve - // its value, apply the delta (e.g. if the delta is a DELETE VALUE X, we have to know whether X matches current - // value of the photo), and if the resulting value is empty, we have to manually delete the RFocusPhoto instance. - // - // So the first step is to retrieve the current value of photo - we obviously do this only if the modifications - // deal with the jpegPhoto property. - Collection> options; - boolean containsFocusPhotoModification = FocusType.class.isAssignableFrom(type) && containsPhotoModification(modifications); - if (containsFocusPhotoModification) { - options = Arrays.asList(SelectorOptions.create(FocusType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); - } else { - options = null; - } - - // TODO skip processing if there are no modifications other than row/case ones - - // get object - PrismObject prismObject = getObject(session, type, oid, options, true); - // apply diff - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT before:\n{}", new Object[]{prismObject.debugDump()}); - } - PrismObject originalObject = null; - if (getClosureManager().isEnabled()) { - originalObject = prismObject.clone(); - } - ItemDelta.applyTo(modifications, prismObject); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT after:\n{}", prismObject.debugDump()); - } - - // Continuing the photo treatment: should we remove the (now obsolete) focus photo? - // We have to test prismObject at this place, because updateFullObject (below) removes photo property from the prismObject. - boolean shouldPhotoBeRemoved = containsFocusPhotoModification && ((FocusType) prismObject.asObjectable()).getJpegPhoto() == null; - - // merge and update object - LOGGER.trace("Translating JAXB to data type."); - RObject rObject = createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); - rObject.setVersion(rObject.getVersion() + 1); - - updateFullObject(rObject, prismObject); - session.merge(rObject); - - lookupTableHelper.updateLookupTableData(session, rObject, lookupTableModifications); - caseHelper.updateCampaignCases(session, rObject, campaignCaseModifications); - - if (getClosureManager().isEnabled()) { - getClosureManager().updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext); - } - - // JpegPhoto cleanup: As said before, if a focus has to have no photo (after modifications are applied), - // we have to remove the photo manually. - if (shouldPhotoBeRemoved) { - Query query = session.createQuery("delete RFocusPhoto where ownerOid = :oid"); - query.setParameter("oid", prismObject.getOid()); - query.executeUpdate(); - LOGGER.trace("Focus photo for {} was deleted", prismObject.getOid()); - } - - LOGGER.trace("Before commit..."); - session.getTransaction().commit(); - LOGGER.trace("Committed!"); - } catch (ObjectNotFoundException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (ConstraintViolationException ex) { - handleConstraintViolationException(session, ex, result); - - rollbackTransaction(session, ex, result, true); - - LOGGER.debug("Constraint violation occurred (will be rethrown as ObjectAlreadyExistsException).", ex); - // we don't know if it's only name uniqueness violation, or something else, - // therefore we're throwing it always as ObjectAlreadyExistsException - - //todo improve (we support only 5 DB, so we should probably do some hacking in here) - throw new ObjectAlreadyExistsException(ex); - } catch (SchemaException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (QueryException | DtoTranslationException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupClosureAndSessionAndResult(closureContext, session, result); - LOGGER.trace("Session cleaned up."); - } - } - - private boolean containsPhotoModification(Collection modifications) { - ItemPath photoPath = new ItemPath(FocusType.F_JPEG_PHOTO); - for (ItemDelta delta : modifications) { - ItemPath path = delta.getPath(); - if (path.isEmpty()) { - throw new UnsupportedOperationException("Focus cannot be modified via empty-path modification"); - } else if (photoPath.isSubPathOrEquivalent(path)) { // actually, "subpath" variant should not occur - return true; - } - } - - return false; - } - - private void cleanupClosureAndSessionAndResult(final OrgClosureManager.Context closureContext, final Session session, final OperationResult result) { - if (closureContext != null) { - getClosureManager().cleanUpAfterOperation(closureContext, session); - } - cleanupSessionAndResult(session, result); - } - - private void handleConstraintViolationException(Session session, ConstraintViolationException ex, OperationResult result) { - - // BRUTAL HACK - in PostgreSQL, concurrent changes in parentRefOrg sometimes cause the following exception - // "duplicate key value violates unique constraint "XXXX". This is *not* an ObjectAlreadyExistsException, - // more likely it is a serialization-related one. - // - // TODO: somewhat generalize this approach - perhaps by retrying all operations not dealing with OID/name uniqueness - - SQLException sqlException = findSqlException(ex); - if (sqlException != null) { - SQLException nextException = sqlException.getNextException(); - LOGGER.debug("ConstraintViolationException = {}; SQL exception = {}; embedded SQL exception = {}", new Object[]{ex, sqlException, nextException}); - String[] ok = new String[]{ - "duplicate key value violates unique constraint \"m_org_closure_pkey\"", - "duplicate key value violates unique constraint \"m_reference_pkey\"" - }; - String msg1; - if (sqlException.getMessage() != null) { - msg1 = sqlException.getMessage(); - } else { - msg1 = ""; - } - String msg2; - if (nextException != null && nextException.getMessage() != null) { - msg2 = nextException.getMessage(); - } else { - msg2 = ""; - } - for (int i = 0; i < ok.length; i++) { - if (msg1.contains(ok[i]) || msg2.contains(ok[i])) { - rollbackTransaction(session, ex, result, false); - throw new SerializationRelatedException(ex); - } - } - } - } - @Override public List> listResourceObjectShadows(String resourceOid, Class resourceObjectShadowType, @@ -1407,7 +540,7 @@ public List> listResourceObjectShadows(Str try { while (true) { try { - return listResourceObjectShadowsAttempt(resourceOid, resourceObjectShadowType, subResult); + return objectRetriever.listResourceObjectShadowsAttempt(resourceOid, resourceObjectShadowType, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(resourceOid, operation, attempt, ex, subResult); pm.registerOperationNewTrial(opHandle, attempt); @@ -1418,85 +551,6 @@ public List> listResourceObjectShadows(Str } } - private List> listResourceObjectShadowsAttempt( - String resourceOid, Class resourceObjectShadowType, OperationResult result) - throws ObjectNotFoundException, SchemaException { - - LOGGER_PERFORMANCE.debug("> list resource object shadows {}, for resource oid={}", - new Object[]{resourceObjectShadowType.getSimpleName(), resourceOid}); - List> list = new ArrayList<>(); - Session session = null; - try { - session = beginReadOnlyTransaction(); - Query query = session.getNamedQuery("listResourceObjectShadows"); - query.setString("oid", resourceOid); - query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); - - List shadows = query.list(); - LOGGER.debug("Query returned {} shadows, transforming to JAXB types.", - new Object[]{(shadows != null ? shadows.size() : 0)}); - - if (shadows != null) { - for (GetObjectResult shadow : shadows) { - PrismObject prismObject = updateLoadedObject(shadow, resourceObjectShadowType, null, session); - list.add(prismObject); - } - } - session.getTransaction().commit(); - } catch (SchemaException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - return list; - } - - private void validateObjectType(PrismObject prismObject, Class type) - throws SchemaException { - if (prismObject == null || !type.isAssignableFrom(prismObject.getCompileTimeClass())) { - throw new SchemaException("Expected to find '" + type.getSimpleName() + "' but found '" - + prismObject.getCompileTimeClass().getSimpleName() + "' (" + prismObject.toDebugName() - + "). Bad OID in a reference?"); - } - if (InternalsConfig.consistencyChecks) { - prismObject.checkConsistence(); - } - if (InternalsConfig.readEncryptionChecks) { - CryptoUtil.checkEncrypted(prismObject); - } - } - - private RObject createDataObjectFromJAXB(PrismObject prismObject, - PrismIdentifierGenerator.Operation operation) - throws SchemaException { - - PrismIdentifierGenerator generator = new PrismIdentifierGenerator(); - IdGeneratorResult generatorResult = generator.generate(prismObject, operation); - - T object = prismObject.asObjectable(); - - RObject rObject; - Class clazz = ClassMapper.getHQLTypeClass(object.getClass()); - try { - rObject = clazz.newInstance(); - Method method = clazz.getMethod("copyFromJAXB", object.getClass(), clazz, - PrismContext.class, IdGeneratorResult.class); - method.invoke(clazz, object, rObject, getPrismContext(), generatorResult); - } catch (Exception ex) { - String message = ex.getMessage(); - if (StringUtils.isEmpty(message) && ex.getCause() != null) { - message = ex.getCause().getMessage(); - } - throw new SchemaException(message, ex); - } - - return rObject; - } - - /* (non-Javadoc) - * @see com.evolveum.midpoint.repo.api.RepositoryService#getRepositoryDiag() - */ @Override public RepositoryDiag getRepositoryDiag() { LOGGER.debug("Getting repository diagnostics."); @@ -1628,15 +682,6 @@ public void testOrgClosureConsistency(boolean repairIfNecessary, OperationResult getClosureManager().checkAndOrRebuild(this, true, repairIfNecessary, false, false, testResult); } - @PostConstruct - public void initialize() { - getClosureManager().initialize(this); - } - - /* (non-Javadoc) - * @see com.evolveum.midpoint.repo.api.RepositoryService#getVersion(java.lang.Class, java.lang.String, - * com.evolveum.midpoint.schema.result.OperationResult) - */ @Override public String getVersion(Class type, String oid, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { @@ -1658,7 +703,7 @@ public String getVersion(Class type, String oid, Opera try { while (true) { try { - return getVersionAttempt(type, oid, subResult); + return objectRetriever.getVersionAttempt(type, oid, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(null, operation, attempt, ex, subResult); pm.registerOperationNewTrial(opHandle, attempt); @@ -1669,37 +714,6 @@ public String getVersion(Class type, String oid, Opera } } - private String getVersionAttempt(Class type, String oid, OperationResult result) - throws ObjectNotFoundException, SchemaException { - LOGGER_PERFORMANCE.debug("> get version {}, oid={}", new Object[]{type.getSimpleName(), oid}); - - String version = null; - Session session = null; - try { - session = beginReadOnlyTransaction(); - Query query = session.getNamedQuery("getVersion"); - query.setString("oid", oid); - - Number versionLong = (Number) query.uniqueResult(); - if (versionLong == null) { - throw new ObjectNotFoundException("Object '" + type.getSimpleName() - + "' with oid '" + oid + "' was not found."); - } - version = versionLong.toString(); - } catch (RuntimeException ex) { - handleGeneralRuntimeException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - return version; - } - - /* (non-Javadoc) - * @see com.evolveum.midpoint.repo.api.RepositoryService#searchObjectsIterative(java.lang.Class, - * com.evolveum.midpoint.prism.query.ObjectQuery, com.evolveum.midpoint.schema.ResultHandler, - * com.evolveum.midpoint.schema.result.OperationResult) - */ @Override public SearchResultMetadata searchObjectsIterative(Class type, ObjectQuery query, ResultHandler handler, @@ -1734,9 +748,9 @@ public SearchResultMetadata searchObjectsIterative(Class< if (getConfiguration().isIterativeSearchByPaging()) { if (strictlySequential) { - searchObjectsIterativeByPagingStrictlySequential(type, query, handler, options, subResult); + objectRetriever.searchObjectsIterativeByPagingStrictlySequential(type, query, handler, options, subResult); } else { - searchObjectsIterativeByPaging(type, query, handler, options, subResult); + objectRetriever.searchObjectsIterativeByPaging(type, query, handler, options, subResult); } return null; } @@ -1750,7 +764,7 @@ public SearchResultMetadata searchObjectsIterative(Class< try { while (true) { try { - searchObjectsIterativeAttempt(type, query, handler, options, subResult); + objectRetriever.searchObjectsIterativeAttempt(type, query, handler, options, subResult); return null; } catch (RuntimeException ex) { attempt = logOperationAttempt(null, operation, attempt, ex, subResult); @@ -1762,197 +776,6 @@ public SearchResultMetadata searchObjectsIterative(Class< } } - private void searchObjectsIterativeAttempt(Class type, ObjectQuery query, - ResultHandler handler, - Collection> options, - OperationResult result) throws SchemaException { - Session session = null; - try { - session = beginReadOnlyTransaction(); - RQuery rQuery; - if (isUseNewQueryInterpreter(query)) { - QueryEngine engine = new QueryEngine(getConfiguration(), getPrismContext()); - rQuery = engine.interpret(query, type, options, false, session); - } else { - QueryEngine2 engine = new QueryEngine2(getConfiguration(), getPrismContext()); - rQuery = engine.interpret(query, type, options, false, session); - } - - ScrollableResults results = rQuery.scroll(ScrollMode.FORWARD_ONLY); - try { - Iterator iterator = new ScrollableResultsIterator(results); - while (iterator.hasNext()) { - GetObjectResult object = iterator.next(); - - PrismObject prismObject = updateLoadedObject(object, type, options, session); - if (!handler.handle(prismObject, result)) { - break; - } - } - } finally { - if (results != null) { - results.close(); - } - } - - session.getTransaction().commit(); - } catch (SchemaException | QueryException | RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - } - - private boolean isUseNewQueryInterpreter(ObjectQuery query) { - return query == null || query.isUseNewQueryInterpreter(); - } - - private void searchObjectsIterativeByPaging(Class type, ObjectQuery query, - ResultHandler handler, - Collection> options, - OperationResult result) - throws SchemaException { - - try { - ObjectQuery pagedQuery = query != null ? query.clone() : new ObjectQuery(); - - int offset; - int remaining; - final int batchSize = getConfiguration().getIterativeSearchByPagingBatchSize(); - - ObjectPaging paging = pagedQuery.getPaging(); - - if (paging == null) { - paging = ObjectPaging.createPaging(0, 0); // counts will be filled-in later - pagedQuery.setPaging(paging); - offset = 0; - remaining = countObjects(type, query, result); - } else { - offset = paging.getOffset() != null ? paging.getOffset() : 0; - remaining = paging.getMaxSize() != null ? paging.getMaxSize() : countObjects(type, query, result) - offset; - } - -main: while (remaining > 0) { - paging.setOffset(offset); - paging.setMaxSize(remaining < batchSize ? remaining : batchSize); - - List> objects = searchObjects(type, pagedQuery, options, result); - - for (PrismObject object : objects) { - if (!handler.handle(object, result)) { - break main; - } - } - - if (objects.size() == 0) { - break; // should not occur, but let's check for this to avoid endless loops - } - offset += objects.size(); - remaining -= objects.size(); - } - } finally { - if (result != null && result.isUnknown()) { - result.computeStatus(); - } - } - } - - // Temporary hack. Represents special paging object that means - // "give me objects with OID greater than specified one, sorted by OID ascending". - // - // TODO: replace by using cookie that is part of the standard ObjectPaging - // (but think out all consequences, e.g. conflicts with the other use of the cookie) - public static class ObjectPagingAfterOid extends ObjectPaging { - private String oidGreaterThan; - - public String getOidGreaterThan() { - return oidGreaterThan; - } - - public void setOidGreaterThan(String oidGreaterThan) { - this.oidGreaterThan = oidGreaterThan; - } - - @Override - public String toString() { - return super.toString() + ", after OID: " + oidGreaterThan; - } - - @Override - public ObjectPagingAfterOid clone() { - ObjectPagingAfterOid clone = new ObjectPagingAfterOid(); - copyTo(clone); - return clone; - } - - protected void copyTo(ObjectPagingAfterOid clone) { - super.copyTo(clone); - clone.oidGreaterThan = this.oidGreaterThan; - } - } - - /** - * Strictly-sequential version of paged search. - * - * Assumptions: - * - During processing of returned object(s), any objects can be added, deleted or modified. - * - * Guarantees: - * - We return each object that existed in the moment of search start: - * - exactly once if it was not deleted in the meanwhile, - * - at most once otherwise. - * - However, we may or may not return any objects that were added during the processing. - * - * Constraints: - * - There can be no ordering prescribed. We use our own ordering. - * - Moreover, for simplicity we disallow any explicit paging. - * - * Implementation is very simple - we fetch objects ordered by OID, and remember last OID fetched. - * Obviously no object will be present in output more than once. - * Objects that are not deleted will be there exactly once, provided their oid is not changed. - */ - private void searchObjectsIterativeByPagingStrictlySequential( - Class type, ObjectQuery query, ResultHandler handler, - Collection> options, OperationResult result) - throws SchemaException { - - try { - ObjectQuery pagedQuery = query != null ? query.clone() : new ObjectQuery(); - - String lastOid = ""; - final int batchSize = getConfiguration().getIterativeSearchByPagingBatchSize(); - - if (pagedQuery.getPaging() != null) { - throw new IllegalArgumentException("Externally specified paging is not supported on strictly sequential iterative search."); - } - - ObjectPagingAfterOid paging = new ObjectPagingAfterOid(); - pagedQuery.setPaging(paging); - -main: for (;;) { - paging.setOidGreaterThan(lastOid); - paging.setMaxSize(batchSize); - - List> objects = searchObjects(type, pagedQuery, options, result); - - for (PrismObject object : objects) { - lastOid = object.getOid(); - if (!handler.handle(object, result)) { - break main; - } - } - - if (objects.size() == 0) { - break; - } - } - } finally { - if (result != null && result.isUnknown()) { - result.computeStatus(); - } - } - } - @Override public boolean isAnySubordinate(String upperOrgOid, Collection lowerObjectOids) throws SchemaException { Validate.notNull(upperOrgOid, "upperOrgOid must not be null."); @@ -1973,7 +796,7 @@ public boolean isAnySubordinate(String upperOrgOid, Collection lowerObje try { while (true) { try { - return isAnySubordinateAttempt(upperOrgOid, lowerObjectOids); + return objectRetriever.isAnySubordinateAttempt(upperOrgOid, lowerObjectOids); } catch (RuntimeException ex) { attempt = logOperationAttempt(upperOrgOid, "isAnySubordinate", attempt, ex, null); pm.registerOperationNewTrial(opHandle, attempt); @@ -1984,31 +807,6 @@ public boolean isAnySubordinate(String upperOrgOid, Collection lowerObje } } - private boolean isAnySubordinateAttempt(String upperOrgOid, Collection lowerObjectOids) { - Session session = null; - try { - session = beginTransaction(); - - Query query; - if (lowerObjectOids.size() == 1) { - query = session.getNamedQuery("isAnySubordinateAttempt.oneLowerOid"); - query.setString("dOid", lowerObjectOids.iterator().next()); - } else { - query = session.getNamedQuery("isAnySubordinateAttempt.moreLowerOids"); - query.setParameterList("dOids", lowerObjectOids); - } - query.setString("aOid", upperOrgOid); - - Number number = (Number) query.uniqueResult(); - return number != null && number.longValue() != 0L; - } catch (RuntimeException ex) { - handleGeneralException(ex, session, null); - } finally { - cleanupSessionAndResult(session, null); - } - - throw new SystemException("isAnySubordinateAttempt failed somehow, this really should not happen."); - } @Override public long advanceSequence(String oid, OperationResult parentResult) throws ObjectNotFoundException, @@ -2030,7 +828,7 @@ public long advanceSequence(String oid, OperationResult parentResult) throws Obj try { while (true) { try { - return advanceSequenceAttempt(oid, result); + return sequenceHelper.advanceSequenceAttempt(oid, result); } catch (RuntimeException ex) { attempt = logOperationAttempt(oid, "advanceSequence", attempt, ex, null); pm.registerOperationNewTrial(opHandle, attempt); @@ -2041,87 +839,8 @@ public long advanceSequence(String oid, OperationResult parentResult) throws Obj } } - private long advanceSequenceAttempt(String oid, OperationResult result) throws ObjectNotFoundException, - SchemaException, SerializationRelatedException { - - long returnValue; - - LOGGER.debug("Advancing sequence with oid '{}'.", oid); - LOGGER_PERFORMANCE.debug("> advance sequence, oid={}", oid); - - Session session = null; - try { - session = beginTransaction(); - - PrismObject prismObject = getObject(session, SequenceType.class, oid, null, true); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT before:\n{}", prismObject.debugDump()); - } - SequenceType sequence = prismObject.asObjectable(); - - if (!sequence.getUnusedValues().isEmpty()) { - returnValue = sequence.getUnusedValues().remove(0); - } else { - long counter = sequence.getCounter() != null ? sequence.getCounter() : 0L; - long maxCounter = sequence.getMaxCounter() != null ? sequence.getMaxCounter() : Long.MAX_VALUE; - boolean allowRewind = Boolean.TRUE.equals(sequence.isAllowRewind()); - - if (counter < maxCounter) { - returnValue = counter; - sequence.setCounter(counter + 1); - } else if (counter == maxCounter) { - returnValue = counter; - if (allowRewind) { - sequence.setCounter(0L); - } else { - sequence.setCounter(counter + 1); // will produce exception during next run - } - } else { // i.e. counter > maxCounter - if (allowRewind) { // shouldn't occur but... - LOGGER.warn("Sequence {} overflown with allowRewind set to true. Rewinding.", oid); - returnValue = 0; - sequence.setCounter(1L); - } else { - // TODO some better exception... - throw new SystemException("No (next) value available from sequence " + oid + ". Current counter = " + sequence.getCounter() + ", max value = " + sequence.getMaxCounter()); - } - } - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Return value = {}, OBJECT after:\n{}", returnValue, prismObject.debugDump()); - } - - // merge and update object - LOGGER.trace("Translating JAXB to data type."); - RObject rObject = createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); - rObject.setVersion(rObject.getVersion() + 1); - - updateFullObject(rObject, prismObject); - session.merge(rObject); - - LOGGER.trace("Before commit..."); - session.getTransaction().commit(); - LOGGER.trace("Committed!"); - - return returnValue; - } catch (ObjectNotFoundException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (SchemaException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (QueryException | DtoTranslationException | RuntimeException ex) { - handleGeneralException(ex, session, result); // should always throw an exception - throw new SystemException("Exception " + ex + " was not handled correctly", ex); // ...so this shouldn't occur at all - } finally { - cleanupSessionAndResult(session, result); - LOGGER.trace("Session cleaned up."); - } - } - - @Override + @Override public void returnUnusedValuesToSequence(String oid, Collection unusedValues, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { Validate.notEmpty(oid, "Oid must not null or empty."); @@ -2145,7 +864,7 @@ public void returnUnusedValuesToSequence(String oid, Collection unusedValu try { while (true) { try { - returnUnusedValuesToSequenceAttempt(oid, unusedValues, result); + sequenceHelper.returnUnusedValuesToSequenceAttempt(oid, unusedValues, result); return; } catch (RuntimeException ex) { attempt = logOperationAttempt(oid, "returnUnusedValuesToSequence", attempt, ex, null); @@ -2157,65 +876,6 @@ public void returnUnusedValuesToSequence(String oid, Collection unusedValu } } - private void returnUnusedValuesToSequenceAttempt(String oid, Collection unusedValues, OperationResult result) throws ObjectNotFoundException, - SchemaException, SerializationRelatedException { - - LOGGER.debug("Returning unused values of {} to a sequence with oid '{}'.", unusedValues, oid); - LOGGER_PERFORMANCE.debug("> return unused values, oid={}, values={}", oid, unusedValues); - - Session session = null; - try { - session = beginTransaction(); - - PrismObject prismObject = getObject(session, SequenceType.class, oid, null, true); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT before:\n{}", prismObject.debugDump()); - } - SequenceType sequence = prismObject.asObjectable(); - int maxUnusedValues = sequence.getMaxUnusedValues() != null ? sequence.getMaxUnusedValues() : 0; - Iterator valuesToReturnIterator = unusedValues.iterator(); - while (valuesToReturnIterator.hasNext() && sequence.getUnusedValues().size() < maxUnusedValues) { - Long valueToReturn = valuesToReturnIterator.next(); - if (valueToReturn == null) { // sanity check - continue; - } - if (!sequence.getUnusedValues().contains(valueToReturn)) { - sequence.getUnusedValues().add(valueToReturn); - } else { - LOGGER.warn("UnusedValues in sequence {} already contains value of {} - ignoring the return request", oid, valueToReturn); - } - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT after:\n{}", prismObject.debugDump()); - } - - // merge and update object - LOGGER.trace("Translating JAXB to data type."); - RObject rObject = createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); - rObject.setVersion(rObject.getVersion() + 1); - - updateFullObject(rObject, prismObject); - session.merge(rObject); - - LOGGER.trace("Before commit..."); - session.getTransaction().commit(); - LOGGER.trace("Committed!"); - } catch (ObjectNotFoundException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (SchemaException ex) { - rollbackTransaction(session, ex, result, true); - throw ex; - } catch (QueryException | DtoTranslationException | RuntimeException ex) { - handleGeneralException(ex, session, result); // should always throw an exception - throw new SystemException("Exception " + ex + " was not handled correctly", ex); // ...so this shouldn't occur at all - } finally { - cleanupSessionAndResult(session, result); - LOGGER.trace("Session cleaned up."); - } - } - @Override public String executeArbitraryQuery(String query, OperationResult result) { Validate.notEmpty(query, "Query must not be empty."); @@ -2235,7 +895,7 @@ public String executeArbitraryQuery(String query, OperationResult result) { try { while (true) { try { - return executeArbitraryQueryAttempt(query, subResult); + return objectRetriever.executeArbitraryQueryAttempt(query, subResult); } catch (RuntimeException ex) { attempt = logOperationAttempt(null, operation, attempt, ex, subResult); pm.registerOperationNewTrial(opHandle, attempt); @@ -2246,50 +906,4 @@ public String executeArbitraryQuery(String query, OperationResult result) { } } - private String executeArbitraryQueryAttempt(String queryString, OperationResult result) { - LOGGER_PERFORMANCE.debug("> execute query {}", queryString); - - Session session = null; - StringBuffer answer = new StringBuffer(); - try { - session = beginReadOnlyTransaction(); // beware, not all databases support read-only transactions! - - Query query = session.createQuery(queryString); - List results = query.list(); - if (results != null) { - answer.append("Result: ").append(results.size()).append(" item(s):\n\n"); - for (Object item : results) { - if (item instanceof Object[]) { - boolean first = true; - for (Object item1 : (Object[]) item) { - if (first) { - first = false; - } else { - answer.append(","); - } - answer.append(item1); - } - } else { - answer.append(item); - } - answer.append("\n"); - } - } - session.getTransaction().rollback(); - } catch (RuntimeException ex) { - handleGeneralException(ex, session, result); - } finally { - cleanupSessionAndResult(session, result); - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Executed query:\n{}\nwith result:\n{}", queryString, answer); - } - - return answer.toString(); - } - - - - } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 36c83ed2f02..67c07403b61 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -352,11 +352,11 @@ private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1 } public AccessCertificationCaseType toJAXB(PrismContext prismContext) throws SchemaException { - return createJaxb(fullObject, prismContext); + return createJaxb(fullObject, prismContext, true); } // TODO find appropriate name - public static AccessCertificationCaseType createJaxb(byte[] fullObject, PrismContext prismContext) throws SchemaException { + public static AccessCertificationCaseType createJaxb(byte[] fullObject, PrismContext prismContext, boolean removeCampaignRef) throws SchemaException { String xml = RUtil.getXmlFromByteArray(fullObject, false); PrismContainer caseContainer; try { @@ -369,6 +369,8 @@ public static AccessCertificationCaseType createJaxb(byte[] fullObject, PrismCon LOGGER.debug("Couldn't parse certification case because of unexpected exception ({}):\nData: {}", e, xml); throw e; } - return caseContainer.getValue().asContainerable().clone(); // clone in order to make it parent-less + AccessCertificationCaseType aCase = caseContainer.getValue().asContainerable().clone(); // clone in order to make it parent-less + aCase.asPrismContainerValue().removeReference(AccessCertificationCaseType.F_CAMPAIGN_REF); + return aCase; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 8976b250f21..97d0006648f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -213,7 +213,7 @@ private void updateCasesContent(Session session, String campaignOid, Collection< if (fullObject == null) { throw new ObjectNotFoundException("Couldn't update cert campaign " + campaignOid + " + by delta with path " + deltaPath + " - specified case does not exist"); } - AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(fullObject, prismContext); + AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(fullObject, prismContext, false); delta.setParentPath(delta.getParentPath().tail(2)); // remove "case[id]" from the delta path delta.applyTo(aCase.asPrismContainerValue()); @@ -254,7 +254,7 @@ public AccessCertificationCaseType updateLoadedCertificationCase(GetObjectResult Collection> options, Session session) throws SchemaException { - AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), prismContext); + AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(result.getFullObject(), prismContext, false); nameResolutionHelper.resolveNamesIfRequested(session, aCase.asPrismContainerValue(), options); generalHelper.validateContainerable(aCase, AccessCertificationCaseType.class); return aCase; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java new file mode 100644 index 00000000000..74ae89095fe --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java @@ -0,0 +1,828 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.common.InternalsConfig; +import com.evolveum.midpoint.common.crypto.CryptoUtil; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismReferenceDefinition; +import com.evolveum.midpoint.prism.parser.XNodeProcessorEvaluationMode; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.sql.ObjectPagingAfterOid; +import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; +import com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.any.RAnyValue; +import com.evolveum.midpoint.repo.sql.data.common.any.RValueType; +import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType; +import com.evolveum.midpoint.repo.sql.query.QueryEngine; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.query.RQuery; +import com.evolveum.midpoint.repo.sql.query2.QueryEngine2; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; +import com.evolveum.midpoint.repo.sql.util.GetObjectResult; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.repo.sql.util.ScrollableResultsIterator; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.ResultHandler; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.hibernate.Criteria; +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.Query; +import org.hibernate.SQLQuery; +import org.hibernate.ScrollMode; +import org.hibernate.ScrollableResults; +import org.hibernate.Session; +import org.hibernate.criterion.Restrictions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * @author lazyman, mederly + */ +@Component +public class ObjectRetriever { + + private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); + private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(SqlRepositoryServiceImpl.PERFORMANCE_LOG_NAME); + + @Autowired + @Qualifier("repositoryService") + private RepositoryService repositoryService; + + @Autowired + private LookupTableHelper lookupTableHelper; + + @Autowired + private CertificationCaseHelper caseHelper; + + @Autowired + private TransactionHelper transactionHelper; + + @Autowired + private NameResolutionHelper nameResolutionHelper; + + @Autowired + private PrismContext prismContext; + + public PrismObject getObjectAttempt(Class type, String oid, + Collection> options, + OperationResult result) + throws ObjectNotFoundException, SchemaException { + LOGGER_PERFORMANCE.debug("> get object {}, oid={}", type.getSimpleName(), oid); + PrismObject objectType = null; + + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + + objectType = getObjectInternal(session, type, oid, options, false); + + session.getTransaction().commit(); + } catch (ObjectNotFoundException ex) { + GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); + transactionHelper.rollbackTransaction(session, ex, result, !GetOperationOptions.isAllowNotFound(rootOptions)); + throw ex; + } catch (SchemaException ex) { + transactionHelper.rollbackTransaction(session, ex, "Schema error while getting object with oid: " + + oid + ". Reason: " + ex.getMessage(), result, true); + throw ex; + } catch (QueryException | DtoTranslationException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Get object:\n{}", new Object[]{(objectType != null ? objectType.debugDump(3) : null)}); + } + + return objectType; + } + + public PrismObject getObjectInternal(Session session, Class type, String oid, + Collection> options, + boolean lockForUpdate) + throws ObjectNotFoundException, SchemaException, DtoTranslationException, QueryException { + + boolean lockedForUpdateViaHibernate = false; + boolean lockedForUpdateViaSql = false; + + LockOptions lockOptions = new LockOptions(); + //todo fix lock for update!!!!! + if (lockForUpdate) { + if (getConfiguration().isLockForUpdateViaHibernate()) { + lockOptions.setLockMode(LockMode.PESSIMISTIC_WRITE); + lockedForUpdateViaHibernate = true; + } else if (getConfiguration().isLockForUpdateViaSql()) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Trying to lock object " + oid + " for update (via SQL)"); + } + long time = System.currentTimeMillis(); + SQLQuery q = session.createSQLQuery("select oid from m_object where oid = ? for update"); + q.setString(0, oid); + Object result = q.uniqueResult(); + if (result == null) { + return throwObjectNotFoundException(type, oid); + } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Locked via SQL (in " + (System.currentTimeMillis() - time) + " ms)"); + } + lockedForUpdateViaSql = true; + } + } + + if (LOGGER.isTraceEnabled()) { + if (lockedForUpdateViaHibernate) { + LOGGER.trace("Getting object " + oid + " with locking for update (via hibernate)"); + } else if (lockedForUpdateViaSql) { + LOGGER.trace("Getting object " + oid + ", already locked for update (via SQL)"); + } else { + LOGGER.trace("Getting object " + oid + " without locking for update"); + } + } + + GetObjectResult fullObject = null; + if (!lockForUpdate) { + Query query = session.getNamedQuery("get.object"); + query.setString("oid", oid); + query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); + query.setLockOptions(lockOptions); + + fullObject = (GetObjectResult) query.uniqueResult(); + } else { + // we're doing update after this get, therefore we load full object right now + // (it would be loaded during merge anyway) + // this just loads object to hibernate session, probably will be removed later. Merge after this get + // will be faster. Read and use object only from fullObject column. + // todo remove this later [lazyman] + Criteria criteria = session.createCriteria(ClassMapper.getHQLTypeClass(type)); + criteria.add(Restrictions.eq("oid", oid)); + + criteria.setLockMode(lockOptions.getLockMode()); + RObject obj = (RObject) criteria.uniqueResult(); + + if (obj != null) { + obj.toJAXB(prismContext, null).asPrismObject(); + fullObject = new GetObjectResult(obj.getFullObject(), obj.getStringsCount(), obj.getLongsCount(), + obj.getDatesCount(), obj.getReferencesCount(), obj.getPolysCount(), obj.getBooleansCount()); + } + } + + LOGGER.trace("Got it."); + if (fullObject == null) { + throwObjectNotFoundException(type, oid); + } + + + LOGGER.trace("Transforming data to JAXB type."); + PrismObject prismObject = updateLoadedObject(fullObject, type, options, session); + validateObjectType(prismObject, type); + + return prismObject; + } + + protected SqlRepositoryConfiguration getConfiguration() { + return ((SqlRepositoryServiceImpl) repositoryService).getConfiguration(); + } + + private PrismObject throwObjectNotFoundException(Class type, String oid) + throws ObjectNotFoundException { + throw new ObjectNotFoundException("Object of type '" + type.getSimpleName() + "' with oid '" + oid + + "' was not found.", null, oid); + } + + public PrismObject searchShadowOwnerAttempt(String shadowOid, Collection> options, OperationResult result) { + LOGGER_PERFORMANCE.debug("> search shadow owner for oid={}", shadowOid); + PrismObject owner = null; + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + LOGGER.trace("Selecting account shadow owner for account {}.", new Object[]{shadowOid}); + Query query = session.getNamedQuery("searchShadowOwner.getOwner"); + query.setString("oid", shadowOid); + query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); + + List focuses = query.list(); + LOGGER.trace("Found {} focuses, transforming data to JAXB types.", + new Object[]{(focuses != null ? focuses.size() : 0)}); + + if (focuses == null || focuses.isEmpty()) { + // account shadow owner was not found + return null; + } + + if (focuses.size() > 1) { + LOGGER.warn("Found {} owners for shadow oid {}, returning first owner.", + new Object[]{focuses.size(), shadowOid}); + } + + GetObjectResult focus = focuses.get(0); + owner = updateLoadedObject(focus, (Class) FocusType.class, options, session); + + session.getTransaction().commit(); + + } catch (SchemaException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return owner; + } + + public PrismObject listAccountShadowOwnerAttempt(String accountOid, OperationResult result) + throws ObjectNotFoundException { + LOGGER_PERFORMANCE.debug("> list account shadow owner oid={}", accountOid); + PrismObject userType = null; + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + Query query = session.getNamedQuery("listAccountShadowOwner.getUser"); + query.setString("oid", accountOid); + query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); + + List users = query.list(); + LOGGER.trace("Found {} users, transforming data to JAXB types.", + new Object[]{(users != null ? users.size() : 0)}); + + if (users == null || users.isEmpty()) { + // account shadow owner was not found + return null; + } + + if (users.size() > 1) { + LOGGER.warn("Found {} users for account oid {}, returning first user. [interface change needed]", + new Object[]{users.size(), accountOid}); + } + + GetObjectResult user = users.get(0); + userType = updateLoadedObject(user, UserType.class, null, session); + + session.getTransaction().commit(); + } catch (SchemaException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return userType; + } + + public int countObjectsAttempt(Class type, ObjectQuery query, OperationResult result) { + LOGGER_PERFORMANCE.debug("> count objects {}", new Object[]{type.getSimpleName()}); + + int count = 0; + + Session session = null; + try { + Class hqlType = ClassMapper.getHQLTypeClass(type); + + session = transactionHelper.beginReadOnlyTransaction(); + Number longCount; + if (query == null || query.getFilter() == null) { + // this is 5x faster than count with 3 inner joins, it can probably improved also for queries which + // filters uses only properties from concrete entities like RUser, RRole by improving interpreter [lazyman] + SQLQuery sqlQuery = session.createSQLQuery("SELECT COUNT(*) FROM " + RUtil.getTableName(hqlType)); + longCount = (Number) sqlQuery.uniqueResult(); + } else { + RQuery rQuery; + if (isUseNewQueryInterpreter(query)) { + QueryEngine2 engine = new QueryEngine2(getConfiguration(), prismContext); + rQuery = engine.interpret(query, type, null, true, session); + } else { + QueryEngine engine = new QueryEngine(getConfiguration(), prismContext); + rQuery = engine.interpret(query, type, null, true, session); + } + + longCount = (Number) rQuery.uniqueResult(); + } + LOGGER.trace("Found {} objects.", longCount); + count = longCount != null ? longCount.intValue() : 0; + } catch (QueryException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return count; + } + + + public SearchResultList> searchObjectsAttempt(Class type, ObjectQuery query, + Collection> options, + OperationResult result) throws SchemaException { + LOGGER_PERFORMANCE.debug("> search objects {}", new Object[]{type.getSimpleName()}); + List> list = new ArrayList<>(); + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + RQuery rQuery; + + if (isUseNewQueryInterpreter(query)) { + QueryEngine2 engine = new QueryEngine2(getConfiguration(), prismContext); + rQuery = engine.interpret(query, type, options, false, session); + } else { + QueryEngine engine = new QueryEngine(getConfiguration(), prismContext); + rQuery = engine.interpret(query, type, options, false, session); + } + + List objects = rQuery.list(); + LOGGER.trace("Found {} objects, translating to JAXB.", new Object[]{(objects != null ? objects.size() : 0)}); + + for (GetObjectResult object : objects) { + PrismObject prismObject = updateLoadedObject(object, type, options, session); + list.add(prismObject); + } + + session.getTransaction().commit(); + } catch (QueryException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return new SearchResultList>(list); + } + + public SearchResultList searchContainersAttempt(Class type, ObjectQuery query, + Collection> options, + OperationResult result) throws SchemaException { + + if (!(AccessCertificationCaseType.class.equals(type))) { + throw new UnsupportedOperationException("Only AccessCertificationCaseType is supported here now."); + } + + LOGGER_PERFORMANCE.debug("> search containers {}", new Object[]{type.getSimpleName()}); + List list = new ArrayList<>(); + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + + QueryEngine2 engine = new QueryEngine2(getConfiguration(), prismContext); + RQuery rQuery = engine.interpret(query, type, options, false, session); + + List items = rQuery.list(); + LOGGER.trace("Found {} items, translating to JAXB.", items.size()); + + for (GetObjectResult item : items) { + C value = (C) caseHelper.updateLoadedCertificationCase(item, options, session); + list.add(value); + } + + session.getTransaction().commit(); + } catch (QueryException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return new SearchResultList(list); + } + + /** + * This method provides object parsing from String and validation. + */ + private PrismObject updateLoadedObject(GetObjectResult result, Class type, + Collection> options, + Session session) throws SchemaException { + + String xml = RUtil.getXmlFromByteArray(result.getFullObject(), getConfiguration().isUseZip()); + PrismObject prismObject; + try { + // "Postel mode": be tolerant what you read. We need this to tolerate (custom) schema changes + prismObject = prismContext.parseObject(xml, XNodeProcessorEvaluationMode.COMPAT); + } catch (SchemaException e) { + LOGGER.debug("Couldn't parse object because of schema exception ({}):\nObject: {}", e, xml); + throw e; + } catch (RuntimeException e) { + LOGGER.debug("Couldn't parse object because of unexpected exception ({}):\nObject: {}", e, xml); + throw e; + } + + if (FocusType.class.isAssignableFrom(prismObject.getCompileTimeClass())) { + if (SelectorOptions.hasToLoadPath(FocusType.F_JPEG_PHOTO, options)) { + //todo improve, use user.hasPhoto flag and take options into account [lazyman] + //this is called only when options contains INCLUDE user/jpegPhoto + Query query = session.getNamedQuery("get.focusPhoto"); + query.setString("oid", prismObject.getOid()); + byte[] photo = (byte[]) query.uniqueResult(); + if (photo != null) { + PrismProperty property = prismObject.findOrCreateProperty(FocusType.F_JPEG_PHOTO); + property.setRealValue(photo); + } + } + } else if (ShadowType.class.equals(prismObject.getCompileTimeClass())) { + //we store it because provisioning now sends it to repo, but it should be transient + prismObject.removeContainer(ShadowType.F_ASSOCIATION); + + LOGGER.debug("Loading definitions for shadow attributes."); + + Short[] counts = result.getCountProjection(); + Class[] classes = GetObjectResult.EXT_COUNT_CLASSES; + + for (int i = 0; i < classes.length; i++) { + if (counts[i] == null || counts[i] == 0) { + continue; + } + + applyShadowAttributeDefinitions(classes[i], prismObject, session); + } + LOGGER.debug("Definitions for attributes loaded. Counts: {}", Arrays.toString(counts)); + } else if (LookupTableType.class.equals(prismObject.getCompileTimeClass())) { + lookupTableHelper.updateLoadedLookupTable(prismObject, options, session); + } else if (AccessCertificationCampaignType.class.equals(prismObject.getCompileTimeClass())) { + caseHelper.updateLoadedCampaign(prismObject, options, session); + } + + nameResolutionHelper.resolveNamesIfRequested(session, prismObject.getValue(), options); + validateObjectType(prismObject, type); + + return prismObject; + } + + + private void applyShadowAttributeDefinitions(Class anyValueType, + PrismObject object, Session session) throws SchemaException { + + PrismContainer attributes = object.findContainer(ShadowType.F_ATTRIBUTES); + + Query query = session.getNamedQuery("getDefinition." + anyValueType.getSimpleName()); + query.setParameter("oid", object.getOid()); + query.setParameter("ownerType", RObjectExtensionType.ATTRIBUTES); + + List values = query.list(); + if (values == null || values.isEmpty()) { + return; + } + + for (Object[] value : values) { + QName name = RUtil.stringToQName((String) value[0]); + QName type = RUtil.stringToQName((String) value[1]); + Item item = attributes.findItem(name); + + // A switch statement used to be here + // but that caused strange trouble with OpenJDK. This if-then-else works. + if (item.getDefinition() == null) { + RValueType rValType = (RValueType) value[2]; + if (rValType == RValueType.PROPERTY) { + PrismPropertyDefinition def = new PrismPropertyDefinition(name, type, object.getPrismContext()); + item.applyDefinition(def, true); + } else if (rValType == RValueType.REFERENCE) { + PrismReferenceDefinition def = new PrismReferenceDefinition(name, type, object.getPrismContext()); + item.applyDefinition(def, true); + } else { + throw new UnsupportedOperationException("Unsupported value type " + rValType); + } + } + } + } + + public List> listResourceObjectShadowsAttempt( + String resourceOid, Class resourceObjectShadowType, OperationResult result) + throws ObjectNotFoundException, SchemaException { + + LOGGER_PERFORMANCE.debug("> list resource object shadows {}, for resource oid={}", + new Object[]{resourceObjectShadowType.getSimpleName(), resourceOid}); + List> list = new ArrayList<>(); + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + Query query = session.getNamedQuery("listResourceObjectShadows"); + query.setString("oid", resourceOid); + query.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); + + List shadows = query.list(); + LOGGER.debug("Query returned {} shadows, transforming to JAXB types.", + new Object[]{(shadows != null ? shadows.size() : 0)}); + + if (shadows != null) { + for (GetObjectResult shadow : shadows) { + PrismObject prismObject = updateLoadedObject(shadow, resourceObjectShadowType, null, session); + list.add(prismObject); + } + } + session.getTransaction().commit(); + } catch (SchemaException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return list; + } + + private void validateObjectType(PrismObject prismObject, Class type) + throws SchemaException { + if (prismObject == null || !type.isAssignableFrom(prismObject.getCompileTimeClass())) { + throw new SchemaException("Expected to find '" + type.getSimpleName() + "' but found '" + + prismObject.getCompileTimeClass().getSimpleName() + "' (" + prismObject.toDebugName() + + "). Bad OID in a reference?"); + } + if (InternalsConfig.consistencyChecks) { + prismObject.checkConsistence(); + } + if (InternalsConfig.readEncryptionChecks) { + CryptoUtil.checkEncrypted(prismObject); + } + } + + public String getVersionAttempt(Class type, String oid, OperationResult result) + throws ObjectNotFoundException, SchemaException { + LOGGER_PERFORMANCE.debug("> get version {}, oid={}", new Object[]{type.getSimpleName(), oid}); + + String version = null; + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + Query query = session.getNamedQuery("getVersion"); + query.setString("oid", oid); + + Number versionLong = (Number) query.uniqueResult(); + if (versionLong == null) { + throw new ObjectNotFoundException("Object '" + type.getSimpleName() + + "' with oid '" + oid + "' was not found."); + } + version = versionLong.toString(); + } catch (RuntimeException ex) { + transactionHelper.handleGeneralRuntimeException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + return version; + } + + public void searchObjectsIterativeAttempt(Class type, ObjectQuery query, + ResultHandler handler, + Collection> options, + OperationResult result) throws SchemaException { + Session session = null; + try { + session = transactionHelper.beginReadOnlyTransaction(); + RQuery rQuery; + if (isUseNewQueryInterpreter(query)) { + QueryEngine engine = new QueryEngine(getConfiguration(), prismContext); + rQuery = engine.interpret(query, type, options, false, session); + } else { + QueryEngine2 engine = new QueryEngine2(getConfiguration(), prismContext); + rQuery = engine.interpret(query, type, options, false, session); + } + + ScrollableResults results = rQuery.scroll(ScrollMode.FORWARD_ONLY); + try { + Iterator iterator = new ScrollableResultsIterator(results); + while (iterator.hasNext()) { + GetObjectResult object = iterator.next(); + + PrismObject prismObject = updateLoadedObject(object, type, options, session); + if (!handler.handle(prismObject, result)) { + break; + } + } + } finally { + if (results != null) { + results.close(); + } + } + + session.getTransaction().commit(); + } catch (SchemaException | QueryException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + } + + public void searchObjectsIterativeByPaging(Class type, ObjectQuery query, + ResultHandler handler, + Collection> options, + OperationResult result) + throws SchemaException { + + try { + ObjectQuery pagedQuery = query != null ? query.clone() : new ObjectQuery(); + + int offset; + int remaining; + final int batchSize = getConfiguration().getIterativeSearchByPagingBatchSize(); + + ObjectPaging paging = pagedQuery.getPaging(); + + if (paging == null) { + paging = ObjectPaging.createPaging(0, 0); // counts will be filled-in later + pagedQuery.setPaging(paging); + offset = 0; + remaining = repositoryService.countObjects(type, query, result); + } else { + offset = paging.getOffset() != null ? paging.getOffset() : 0; + remaining = paging.getMaxSize() != null ? paging.getMaxSize() : repositoryService.countObjects(type, query, result) - offset; + } + +main: while (remaining > 0) { + paging.setOffset(offset); + paging.setMaxSize(remaining < batchSize ? remaining : batchSize); + + List> objects = repositoryService.searchObjects(type, pagedQuery, options, result); + + for (PrismObject object : objects) { + if (!handler.handle(object, result)) { + break main; + } + } + + if (objects.size() == 0) { + break; // should not occur, but let's check for this to avoid endless loops + } + offset += objects.size(); + remaining -= objects.size(); + } + } finally { + if (result != null && result.isUnknown()) { + result.computeStatus(); + } + } + } + + /** + * Strictly-sequential version of paged search. + * + * Assumptions: + * - During processing of returned object(s), any objects can be added, deleted or modified. + * + * Guarantees: + * - We return each object that existed in the moment of search start: + * - exactly once if it was not deleted in the meanwhile, + * - at most once otherwise. + * - However, we may or may not return any objects that were added during the processing. + * + * Constraints: + * - There can be no ordering prescribed. We use our own ordering. + * - Moreover, for simplicity we disallow any explicit paging. + * + * Implementation is very simple - we fetch objects ordered by OID, and remember last OID fetched. + * Obviously no object will be present in output more than once. + * Objects that are not deleted will be there exactly once, provided their oid is not changed. + */ + public void searchObjectsIterativeByPagingStrictlySequential( + Class type, ObjectQuery query, ResultHandler handler, + Collection> options, OperationResult result) + throws SchemaException { + + try { + ObjectQuery pagedQuery = query != null ? query.clone() : new ObjectQuery(); + + String lastOid = ""; + final int batchSize = getConfiguration().getIterativeSearchByPagingBatchSize(); + + if (pagedQuery.getPaging() != null) { + throw new IllegalArgumentException("Externally specified paging is not supported on strictly sequential iterative search."); + } + + ObjectPagingAfterOid paging = new ObjectPagingAfterOid(); + pagedQuery.setPaging(paging); +main: for (;;) { + paging.setOidGreaterThan(lastOid); + paging.setMaxSize(batchSize); + + List> objects = repositoryService.searchObjects(type, pagedQuery, options, result); + + for (PrismObject object : objects) { + lastOid = object.getOid(); + if (!handler.handle(object, result)) { + break main; + } + } + + if (objects.size() == 0) { + break; + } + } + } finally { + if (result != null && result.isUnknown()) { + result.computeStatus(); + } + } + } + + public boolean isAnySubordinateAttempt(String upperOrgOid, Collection lowerObjectOids) { + Session session = null; + try { + session = transactionHelper.beginTransaction(); + + Query query; + if (lowerObjectOids.size() == 1) { + query = session.getNamedQuery("isAnySubordinateAttempt.oneLowerOid"); + query.setString("dOid", lowerObjectOids.iterator().next()); + } else { + query = session.getNamedQuery("isAnySubordinateAttempt.moreLowerOids"); + query.setParameterList("dOids", lowerObjectOids); + } + query.setString("aOid", upperOrgOid); + + Number number = (Number) query.uniqueResult(); + return number != null && number.longValue() != 0L; + } catch (RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, null); + } finally { + transactionHelper.cleanupSessionAndResult(session, null); + } + + throw new SystemException("isAnySubordinateAttempt failed somehow, this really should not happen."); + } + + public String executeArbitraryQueryAttempt(String queryString, OperationResult result) { + LOGGER_PERFORMANCE.debug("> execute query {}", queryString); + + Session session = null; + StringBuffer answer = new StringBuffer(); + try { + session = transactionHelper.beginReadOnlyTransaction(); // beware, not all databases support read-only transactions! + + Query query = session.createQuery(queryString); + List results = query.list(); + if (results != null) { + answer.append("Result: ").append(results.size()).append(" item(s):\n\n"); + for (Object item : results) { + if (item instanceof Object[]) { + boolean first = true; + for (Object item1 : (Object[]) item) { + if (first) { + first = false; + } else { + answer.append(","); + } + answer.append(item1); + } + } else { + answer.append(item); + } + answer.append("\n"); + } + } + session.getTransaction().rollback(); + } catch (RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Executed query:\n{}\nwith result:\n{}", queryString, answer); + } + + return answer.toString(); + } + + private boolean isUseNewQueryInterpreter(ObjectQuery query) { + return query == null || query.isUseNewQueryInterpreter(); + } + + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java new file mode 100644 index 00000000000..e0a70115a48 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismReference; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.ReferenceDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.api.RepoAddOptions; +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.sql.SerializationRelatedException; +import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; +import com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.util.ClassMapper; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; +import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; +import com.evolveum.midpoint.repo.sql.util.PrismIdentifierGenerator; +import com.evolveum.midpoint.repo.sql.util.RUtil; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.RetrieveOption; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Criteria; +import org.hibernate.Query; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.criterion.Restrictions; +import org.hibernate.exception.ConstraintViolationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * @author lazyman, mederly + */ + +@Component +public class ObjectUpdater { + + private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); + private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(SqlRepositoryServiceImpl.PERFORMANCE_LOG_NAME); + + @Autowired + @Qualifier("repositoryService") + private RepositoryService repositoryService; + + @Autowired + private TransactionHelper transactionHelper; + + @Autowired + private ObjectRetriever objectRetriever; + + @Autowired + private LookupTableHelper lookupTableHelper; + + @Autowired + private CertificationCaseHelper caseHelper; + + @Autowired + private OrgClosureManager closureManager; + + @Autowired + private PrismContext prismContext; + + public String addObjectAttempt(PrismObject object, RepoAddOptions options, + OperationResult result) throws ObjectAlreadyExistsException, SchemaException { + + LOGGER_PERFORMANCE.debug("> add object {}, oid={}, overwrite={}", + object.getCompileTimeClass().getSimpleName(), object.getOid(), options.isOverwrite()); + + String oid = null; + Session session = null; + OrgClosureManager.Context closureContext = null; + // it is needed to keep the original oid for example for import options. if we do not keep it + // and it was null it can bring some error because the oid is set when the object contains orgRef + // or it is org. and by the import we do not know it so it will be trying to delete non-existing object + String originalOid = object.getOid(); + try { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Object\n{}", new Object[]{object.debugDump()}); + } + + LOGGER.trace("Translating JAXB to data type."); + PrismIdentifierGenerator.Operation operation = options.isOverwrite() ? + PrismIdentifierGenerator.Operation.ADD_WITH_OVERWRITE : + PrismIdentifierGenerator.Operation.ADD; + + RObject rObject = createDataObjectFromJAXB(object, operation); + + session = beginTransaction(); + + closureContext = closureManager.onBeginTransactionAdd(session, object, options.isOverwrite()); + + if (options.isOverwrite()) { + oid = overwriteAddObjectAttempt(object, rObject, originalOid, session, closureContext); + } else { + oid = nonOverwriteAddObjectAttempt(object, rObject, originalOid, session, closureContext); + } + session.getTransaction().commit(); + + LOGGER.trace("Saved object '{}' with oid '{}'", new Object[]{ + object.getCompileTimeClass().getSimpleName(), oid}); + + object.setOid(oid); + } catch (ConstraintViolationException ex) { + handleConstraintViolationException(session, ex, result); + transactionHelper.rollbackTransaction(session, ex, result, true); + + LOGGER.debug("Constraint violation occurred (will be rethrown as ObjectAlreadyExistsException).", ex); + // we don't know if it's only name uniqueness violation, or something else, + // therefore we're throwing it always as ObjectAlreadyExistsException revert + // to the original oid and prevent of unexpected behaviour (e.g. by import with overwrite option) + if (StringUtils.isEmpty(originalOid)) { + object.setOid(null); + } + String constraintName = ex.getConstraintName(); + // Breaker to avoid long unreadable messages + if (constraintName != null && constraintName.length() > SqlRepositoryServiceImpl.MAX_CONSTRAINT_NAME_LENGTH) { + constraintName = null; + } + throw new ObjectAlreadyExistsException("Conflicting object already exists" + + (constraintName == null ? "" : " (violated constraint '" + constraintName + "')"), ex); + } catch (ObjectAlreadyExistsException | SchemaException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (DtoTranslationException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + cleanupClosureAndSessionAndResult(closureContext, session, result); + } + + return oid; + } + + private Session beginTransaction() { + return transactionHelper.beginTransaction(); + } + + private String overwriteAddObjectAttempt(PrismObject object, RObject rObject, + String originalOid, Session session, OrgClosureManager.Context closureContext) + throws ObjectAlreadyExistsException, SchemaException, DtoTranslationException { + + PrismObject oldObject = null; + + //check if object already exists, find differences and increment version if necessary + Collection modifications = null; + if (originalOid != null) { + try { + oldObject = objectRetriever.getObjectInternal(session, object.getCompileTimeClass(), originalOid, null, true); + ObjectDelta delta = object.diff(oldObject); + modifications = delta.getModifications(); + + //we found existing object which will be overwritten, therefore we increment version + Integer version = RUtil.getIntegerFromString(oldObject.getVersion()); + version = (version == null) ? 0 : ++version; + + rObject.setVersion(version); + } catch (QueryException ex) { + transactionHelper.handleGeneralCheckedException(ex, session, null); + } catch (ObjectNotFoundException ex) { + //it's ok that object was not found, therefore we won't be overwriting it + } + } + + updateFullObject(rObject, object); + RObject merged = (RObject) session.merge(rObject); + lookupTableHelper.addLookupTableRows(session, rObject, modifications != null); + caseHelper.addCertificationCampaignCases(session, rObject, modifications != null); + + if (closureManager.isEnabled()) { + OrgClosureManager.Operation operation; + if (modifications == null) { + operation = OrgClosureManager.Operation.ADD; + modifications = createAddParentRefDelta(object); + } else { + operation = OrgClosureManager.Operation.MODIFY; + } + closureManager.updateOrgClosure(oldObject, modifications, session, merged.getOid(), object.getCompileTimeClass(), + operation, closureContext); + } + return merged.getOid(); + } + + private List createAddParentRefDelta(PrismObject object) { + PrismReference parentOrgRef = object.findReference(ObjectType.F_PARENT_ORG_REF); + if (parentOrgRef == null || parentOrgRef.isEmpty()) { + return new ArrayList<>(); + } + + PrismObjectDefinition def = object.getDefinition(); + ReferenceDelta delta = ReferenceDelta.createModificationAdd(new ItemPath(ObjectType.F_PARENT_ORG_REF), + def, parentOrgRef.getClonedValues()); + + return Arrays.asList(delta); + } + + public void updateFullObject(RObject object, PrismObject savedObject) + throws DtoTranslationException, SchemaException { + LOGGER.debug("Updating full object xml column start."); + savedObject.setVersion(Integer.toString(object.getVersion())); + + if (FocusType.class.isAssignableFrom(savedObject.getCompileTimeClass())) { + savedObject.removeProperty(FocusType.F_JPEG_PHOTO); + } else if (LookupTableType.class.equals(savedObject.getCompileTimeClass())) { + PrismContainer table = savedObject.findContainer(LookupTableType.F_ROW); + savedObject.remove(table); + } else if (AccessCertificationCampaignType.class.equals(savedObject.getCompileTimeClass())) { + PrismContainer caseContainer = savedObject.findContainer(AccessCertificationCampaignType.F_CASE); + savedObject.remove(caseContainer); + } + + String xml = prismContext.serializeObjectToString(savedObject, PrismContext.LANG_XML); + byte[] fullObject = RUtil.getByteArrayFromXml(xml, getConfiguration().isUseZip()); + + if (LOGGER.isTraceEnabled()) LOGGER.trace("Storing full object\n{}", xml); + + object.setFullObject(fullObject); + + LOGGER.debug("Updating full object xml column finish."); + } + + protected SqlRepositoryConfiguration getConfiguration() { + return ((SqlRepositoryServiceImpl) repositoryService).getConfiguration(); + } + + private String nonOverwriteAddObjectAttempt(PrismObject object, RObject rObject, + String originalOid, Session session, OrgClosureManager.Context closureContext) + throws ObjectAlreadyExistsException, SchemaException, DtoTranslationException { + + // check name uniqueness (by type) + if (StringUtils.isNotEmpty(originalOid)) { + LOGGER.trace("Checking oid uniqueness."); + //todo improve this table name bullshit + Class hqlType = ClassMapper.getHQLTypeClass(object.getCompileTimeClass()); + SQLQuery query = session.createSQLQuery("select count(*) from " + RUtil.getTableName(hqlType) + + " where oid=:oid"); + query.setString("oid", object.getOid()); + + Number count = (Number) query.uniqueResult(); + if (count != null && count.longValue() > 0) { + throw new ObjectAlreadyExistsException("Object '" + object.getCompileTimeClass().getSimpleName() + + "' with oid '" + object.getOid() + "' already exists."); + } + } + + updateFullObject(rObject, object); + + LOGGER.trace("Saving object (non overwrite)."); + String oid = (String) session.save(rObject); + lookupTableHelper.addLookupTableRows(session, rObject, false); + caseHelper.addCertificationCampaignCases(session, rObject, false); + + if (closureManager.isEnabled()) { + Collection modifications = createAddParentRefDelta(object); + closureManager.updateOrgClosure(null, modifications, session, oid, object.getCompileTimeClass(), + OrgClosureManager.Operation.ADD, closureContext); + } + + return oid; + } + + + public void deleteObjectAttempt(Class type, String oid, OperationResult result) + throws ObjectNotFoundException { + LOGGER_PERFORMANCE.debug("> delete object {}, oid={}", new Object[]{type.getSimpleName(), oid}); + Session session = null; + OrgClosureManager.Context closureContext = null; + try { + session = beginTransaction(); + + closureContext = closureManager.onBeginTransactionDelete(session, type, oid); + + Criteria query = session.createCriteria(ClassMapper.getHQLTypeClass(type)); + query.add(Restrictions.eq("oid", oid)); + RObject object = (RObject) query.uniqueResult(); + if (object == null) { + throw new ObjectNotFoundException("Object of type '" + type.getSimpleName() + "' with oid '" + oid + + "' was not found.", null, oid); + } + + closureManager.updateOrgClosure(null, null, session, oid, type, OrgClosureManager.Operation.DELETE, closureContext); + + session.delete(object); + if (LookupTableType.class.equals(type)) { + lookupTableHelper.deleteLookupTableRows(session, oid); + } + if (AccessCertificationCampaignType.class.equals(type)) { + caseHelper.deleteCertificationCampaignCases(session, oid); + } + + session.getTransaction().commit(); + } catch (ObjectNotFoundException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + cleanupClosureAndSessionAndResult(closureContext, session, result); + } + } + + public void modifyObjectAttempt(Class type, String oid, + Collection modifications, + OperationResult result) throws ObjectNotFoundException, + SchemaException, ObjectAlreadyExistsException, SerializationRelatedException { + + // shallow clone - because some methods, e.g. filterLookupTableModifications manipulate this collection + modifications = new ArrayList<>(modifications); + + LOGGER.debug("Modifying object '{}' with oid '{}'.", new Object[]{type.getSimpleName(), oid}); + LOGGER_PERFORMANCE.debug("> modify object {}, oid={}, modifications={}", + new Object[]{type.getSimpleName(), oid, modifications}); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Modifications:\n{}", new Object[]{DebugUtil.debugDump(modifications)}); + } + + Session session = null; + OrgClosureManager.Context closureContext = null; + try { + session = beginTransaction(); + + closureContext = closureManager.onBeginTransactionModify(session, type, oid, modifications); + + Collection lookupTableModifications = lookupTableHelper.filterLookupTableModifications(type, modifications); + Collection campaignCaseModifications = caseHelper.filterCampaignCaseModifications(type, modifications); + + // JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big. + // Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo + // association. However, this leads to a strange problem when merging in-memory RFocus object with the database state: + // If in-memory RFocus object has no photo associated (because of lazy loading), then the associated RFocusPhoto is deleted. + // + // To prevent this behavior, we've set orphanRemoval to false. Fortunately, the remove operation on RFocus + // seems to be still cascaded to RFocusPhoto. What we have to implement ourselves, however, is removal of RFocusPhoto + // _without_ removing of RFocus. In order to know whether the photo has to be removed, we have to retrieve + // its value, apply the delta (e.g. if the delta is a DELETE VALUE X, we have to know whether X matches current + // value of the photo), and if the resulting value is empty, we have to manually delete the RFocusPhoto instance. + // + // So the first step is to retrieve the current value of photo - we obviously do this only if the modifications + // deal with the jpegPhoto property. + Collection> options; + boolean containsFocusPhotoModification = FocusType.class.isAssignableFrom(type) && containsPhotoModification(modifications); + if (containsFocusPhotoModification) { + options = Arrays.asList(SelectorOptions.create(FocusType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); + } else { + options = null; + } + + // TODO skip processing if there are no modifications other than row/case ones + + // get object + PrismObject prismObject = objectRetriever.getObjectInternal(session, type, oid, options, true); + // apply diff + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT before:\n{}", new Object[]{prismObject.debugDump()}); + } + PrismObject originalObject = null; + if (closureManager.isEnabled()) { + originalObject = prismObject.clone(); + } + ItemDelta.applyTo(modifications, prismObject); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT after:\n{}", prismObject.debugDump()); + } + + // Continuing the photo treatment: should we remove the (now obsolete) focus photo? + // We have to test prismObject at this place, because updateFullObject (below) removes photo property from the prismObject. + boolean shouldPhotoBeRemoved = containsFocusPhotoModification && ((FocusType) prismObject.asObjectable()).getJpegPhoto() == null; + + // merge and update object + LOGGER.trace("Translating JAXB to data type."); + RObject rObject = createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); + rObject.setVersion(rObject.getVersion() + 1); + + updateFullObject(rObject, prismObject); + session.merge(rObject); + + lookupTableHelper.updateLookupTableData(session, rObject, lookupTableModifications); + caseHelper.updateCampaignCases(session, rObject, campaignCaseModifications); + + if (closureManager.isEnabled()) { + closureManager.updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext); + } + + // JpegPhoto cleanup: As said before, if a focus has to have no photo (after modifications are applied), + // we have to remove the photo manually. + if (shouldPhotoBeRemoved) { + Query query = session.createQuery("delete RFocusPhoto where ownerOid = :oid"); + query.setParameter("oid", prismObject.getOid()); + query.executeUpdate(); + LOGGER.trace("Focus photo for {} was deleted", prismObject.getOid()); + } + + LOGGER.trace("Before commit..."); + session.getTransaction().commit(); + LOGGER.trace("Committed!"); + } catch (ObjectNotFoundException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (ConstraintViolationException ex) { + handleConstraintViolationException(session, ex, result); + + transactionHelper.rollbackTransaction(session, ex, result, true); + + LOGGER.debug("Constraint violation occurred (will be rethrown as ObjectAlreadyExistsException).", ex); + // we don't know if it's only name uniqueness violation, or something else, + // therefore we're throwing it always as ObjectAlreadyExistsException + + //todo improve (we support only 5 DB, so we should probably do some hacking in here) + throw new ObjectAlreadyExistsException(ex); + } catch (SchemaException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (QueryException | DtoTranslationException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); + } finally { + cleanupClosureAndSessionAndResult(closureContext, session, result); + LOGGER.trace("Session cleaned up."); + } + } + + private boolean containsPhotoModification(Collection modifications) { + ItemPath photoPath = new ItemPath(FocusType.F_JPEG_PHOTO); + for (ItemDelta delta : modifications) { + ItemPath path = delta.getPath(); + if (path.isEmpty()) { + throw new UnsupportedOperationException("Focus cannot be modified via empty-path modification"); + } else if (photoPath.isSubPathOrEquivalent(path)) { // actually, "subpath" variant should not occur + return true; + } + } + + return false; + } + + private void cleanupClosureAndSessionAndResult(final OrgClosureManager.Context closureContext, final Session session, final OperationResult result) { + if (closureContext != null) { + closureManager.cleanUpAfterOperation(closureContext, session); + } + transactionHelper.cleanupSessionAndResult(session, result); + } + + private void handleConstraintViolationException(Session session, ConstraintViolationException ex, OperationResult result) { + + // BRUTAL HACK - in PostgreSQL, concurrent changes in parentRefOrg sometimes cause the following exception + // "duplicate key value violates unique constraint "XXXX". This is *not* an ObjectAlreadyExistsException, + // more likely it is a serialization-related one. + // + // TODO: somewhat generalize this approach - perhaps by retrying all operations not dealing with OID/name uniqueness + + SQLException sqlException = transactionHelper.findSqlException(ex); + if (sqlException != null) { + SQLException nextException = sqlException.getNextException(); + LOGGER.debug("ConstraintViolationException = {}; SQL exception = {}; embedded SQL exception = {}", new Object[]{ex, sqlException, nextException}); + String[] ok = new String[]{ + "duplicate key value violates unique constraint \"m_org_closure_pkey\"", + "duplicate key value violates unique constraint \"m_reference_pkey\"" + }; + String msg1; + if (sqlException.getMessage() != null) { + msg1 = sqlException.getMessage(); + } else { + msg1 = ""; + } + String msg2; + if (nextException != null && nextException.getMessage() != null) { + msg2 = nextException.getMessage(); + } else { + msg2 = ""; + } + for (int i = 0; i < ok.length; i++) { + if (msg1.contains(ok[i]) || msg2.contains(ok[i])) { + transactionHelper.rollbackTransaction(session, ex, result, false); + throw new SerializationRelatedException(ex); + } + } + } + } + + public RObject createDataObjectFromJAXB(PrismObject prismObject, + PrismIdentifierGenerator.Operation operation) + throws SchemaException { + + PrismIdentifierGenerator generator = new PrismIdentifierGenerator(); + IdGeneratorResult generatorResult = generator.generate(prismObject, operation); + + T object = prismObject.asObjectable(); + + RObject rObject; + Class clazz = ClassMapper.getHQLTypeClass(object.getClass()); + try { + rObject = clazz.newInstance(); + Method method = clazz.getMethod("copyFromJAXB", object.getClass(), clazz, + PrismContext.class, IdGeneratorResult.class); + method.invoke(clazz, object, rObject, prismContext, generatorResult); + } catch (Exception ex) { + String message = ex.getMessage(); + if (StringUtils.isEmpty(message) && ex.getCause() != null) { + message = ex.getCause().getMessage(); + } + throw new SchemaException(message, ex); + } + + return rObject; + } + +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/OrgClosureManager.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/OrgClosureManager.java similarity index 97% rename from repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/OrgClosureManager.java rename to repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/OrgClosureManager.java index dd0d9aa3280..ea8c7af8248 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/OrgClosureManager.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/OrgClosureManager.java @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.evolveum.midpoint.repo.sql; +package com.evolveum.midpoint.repo.sql.helpers; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; +import com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl; import com.evolveum.midpoint.repo.sql.data.common.ROrgClosure; import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType; import com.evolveum.midpoint.schema.ResultHandler; @@ -45,7 +47,11 @@ import org.hibernate.tool.hbm2ddl.SchemaUpdate; import org.hibernate.type.IntegerType; import org.hibernate.type.StringType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -71,21 +77,20 @@ * @author lazyman * @author mederly */ +@Component +@DependsOn("repositoryService") public class OrgClosureManager { private static final Trace LOGGER = TraceManager.getTrace(OrgClosureManager.class); + @Autowired + private SqlRepositoryServiceImpl sqlRepositoryService; + private static boolean DUMP_TABLES = false; private static final boolean COUNT_CLOSURE_RECORDS = false; static final String CLOSURE_TABLE_NAME = "m_org_closure"; public static final String TEMP_DELTA_TABLE_NAME_FOR_ORACLE = "m_org_closure_temp_delta"; - private SqlRepositoryConfiguration repoConfiguration; - - public OrgClosureManager(SqlRepositoryConfiguration repoConfiguration) { - this.repoConfiguration = repoConfiguration; - } - // only for single-thread performance testing long lastOperationDuration; @@ -214,19 +219,22 @@ public void cleanUpAfterOperation(Context closureContext, Session session) { } } - public void initialize(SqlRepositoryServiceImpl service) { + @PostConstruct + public void initialize() { OperationResult result = new OperationResult(OrgClosureManager.class.getName() + ".initialize"); if (!isEnabled()) { return; } + SqlRepositoryConfiguration repoConfiguration = sqlRepositoryService.getConfiguration(); + if (isOracle()) { - initializeOracleTemporaryTable(service); + initializeOracleTemporaryTable(sqlRepositoryService); } - if (autoUpdateClosureTableStructure(service)) { + if (autoUpdateClosureTableStructure(sqlRepositoryService)) { // need to rebuild the content of the closure table after re-creating it anew - checkAndOrRebuild(service, false, true, repoConfiguration.isStopOnOrgClosureStartupFailure(), true, result); + checkAndOrRebuild(sqlRepositoryService, false, true, repoConfiguration.isStopOnOrgClosureStartupFailure(), true, result); } else { boolean check, rebuild; switch (repoConfiguration.getOrgClosureStartupAction()) { @@ -247,7 +255,7 @@ public void initialize(SqlRepositoryServiceImpl service) { default: throw new IllegalArgumentException("Invalid value: " + repoConfiguration.getOrgClosureStartupAction()); } - checkAndOrRebuild(service, check, rebuild, repoConfiguration.isStopOnOrgClosureStartupFailure(), true, result); + checkAndOrRebuild(sqlRepositoryService, check, rebuild, repoConfiguration.isStopOnOrgClosureStartupFailure(), true, result); } } @@ -261,7 +269,7 @@ public void initialize(SqlRepositoryServiceImpl service) { // returns true if the table was re-created private boolean autoUpdateClosureTableStructure(SqlRepositoryServiceImpl service) { - if (repoConfiguration.isSkipOrgClosureStructureCheck()) { + if (sqlRepositoryService.getConfiguration().isSkipOrgClosureStructureCheck()) { LOGGER.debug("Skipping org closure structure check."); return false; } @@ -339,7 +347,7 @@ public void execute(Connection connection) throws SQLException { } public boolean isEnabled() { - return !repoConfiguration.isIgnoreOrgClosure(); + return !sqlRepositoryService.getConfiguration().isIgnoreOrgClosure(); } /** @@ -1307,23 +1315,23 @@ private List retainExistingOids(Collection oids, Session session } private boolean isMySQL() { - return repoConfiguration.isUsingMySQL(); + return sqlRepositoryService.getConfiguration().isUsingMySQL(); } private boolean isOracle() { - return repoConfiguration.isUsingOracle(); + return sqlRepositoryService.getConfiguration().isUsingOracle(); } private boolean isSQLServer() { - return repoConfiguration.isUsingSQLServer(); + return sqlRepositoryService.getConfiguration().isUsingSQLServer(); } private boolean isH2() { - return repoConfiguration.isUsingH2(); + return sqlRepositoryService.getConfiguration().isUsingH2(); } private boolean isPostgreSQL() { - return repoConfiguration.isUsingPostgreSQL(); + return sqlRepositoryService.getConfiguration().isUsingPostgreSQL(); } //endregion diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/SequenceHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/SequenceHelper.java new file mode 100644 index 00000000000..a1541bd2181 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/SequenceHelper.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.repo.sql.SerializationRelatedException; +import com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl; +import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.query.QueryException; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; +import com.evolveum.midpoint.repo.sql.util.PrismIdentifierGenerator; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SequenceType; +import org.hibernate.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.Iterator; + +/** + * @author mederly + */ +@Component +public class SequenceHelper { + + @Autowired + private ObjectRetriever objectRetriever; + + @Autowired + private ObjectUpdater objectUpdater; + + @Autowired + private TransactionHelper transactionHelper; + + private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); + private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(SqlRepositoryServiceImpl.PERFORMANCE_LOG_NAME); + + public long advanceSequenceAttempt(String oid, OperationResult result) throws ObjectNotFoundException, + SchemaException, SerializationRelatedException { + + long returnValue; + + LOGGER.debug("Advancing sequence with oid '{}'.", oid); + LOGGER_PERFORMANCE.debug("> advance sequence, oid={}", oid); + + Session session = null; + try { + session = transactionHelper.beginTransaction(); + + PrismObject prismObject = objectRetriever.getObjectInternal(session, SequenceType.class, oid, null, true); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT before:\n{}", prismObject.debugDump()); + } + SequenceType sequence = prismObject.asObjectable(); + + if (!sequence.getUnusedValues().isEmpty()) { + returnValue = sequence.getUnusedValues().remove(0); + } else { + long counter = sequence.getCounter() != null ? sequence.getCounter() : 0L; + long maxCounter = sequence.getMaxCounter() != null ? sequence.getMaxCounter() : Long.MAX_VALUE; + boolean allowRewind = Boolean.TRUE.equals(sequence.isAllowRewind()); + + if (counter < maxCounter) { + returnValue = counter; + sequence.setCounter(counter + 1); + } else if (counter == maxCounter) { + returnValue = counter; + if (allowRewind) { + sequence.setCounter(0L); + } else { + sequence.setCounter(counter + 1); // will produce exception during next run + } + } else { // i.e. counter > maxCounter + if (allowRewind) { // shouldn't occur but... + LOGGER.warn("Sequence {} overflown with allowRewind set to true. Rewinding.", oid); + returnValue = 0; + sequence.setCounter(1L); + } else { + // TODO some better exception... + throw new SystemException("No (next) value available from sequence " + oid + ". Current counter = " + sequence.getCounter() + ", max value = " + sequence.getMaxCounter()); + } + } + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Return value = {}, OBJECT after:\n{}", returnValue, prismObject.debugDump()); + } + + // merge and update object + LOGGER.trace("Translating JAXB to data type."); + RObject rObject = objectUpdater.createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); + rObject.setVersion(rObject.getVersion() + 1); + + objectUpdater.updateFullObject(rObject, prismObject); + session.merge(rObject); + + LOGGER.trace("Before commit..."); + session.getTransaction().commit(); + LOGGER.trace("Committed!"); + + return returnValue; + } catch (ObjectNotFoundException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (SchemaException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (QueryException | DtoTranslationException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); // should always throw an exception + throw new SystemException("Exception " + ex + " was not handled correctly", ex); // ...so this shouldn't occur at all + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + LOGGER.trace("Session cleaned up."); + } + } + + public void returnUnusedValuesToSequenceAttempt(String oid, Collection unusedValues, OperationResult result) throws ObjectNotFoundException, + SchemaException, SerializationRelatedException { + + LOGGER.debug("Returning unused values of {} to a sequence with oid '{}'.", unusedValues, oid); + LOGGER_PERFORMANCE.debug("> return unused values, oid={}, values={}", oid, unusedValues); + + Session session = null; + try { + session = transactionHelper.beginTransaction(); + + PrismObject prismObject = objectRetriever.getObjectInternal(session, SequenceType.class, oid, null, true); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT before:\n{}", prismObject.debugDump()); + } + SequenceType sequence = prismObject.asObjectable(); + int maxUnusedValues = sequence.getMaxUnusedValues() != null ? sequence.getMaxUnusedValues() : 0; + Iterator valuesToReturnIterator = unusedValues.iterator(); + while (valuesToReturnIterator.hasNext() && sequence.getUnusedValues().size() < maxUnusedValues) { + Long valueToReturn = valuesToReturnIterator.next(); + if (valueToReturn == null) { // sanity check + continue; + } + if (!sequence.getUnusedValues().contains(valueToReturn)) { + sequence.getUnusedValues().add(valueToReturn); + } else { + LOGGER.warn("UnusedValues in sequence {} already contains value of {} - ignoring the return request", oid, valueToReturn); + } + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT after:\n{}", prismObject.debugDump()); + } + + // merge and update object + LOGGER.trace("Translating JAXB to data type."); + RObject rObject = objectUpdater.createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); + rObject.setVersion(rObject.getVersion() + 1); + + objectUpdater.updateFullObject(rObject, prismObject); + session.merge(rObject); + + LOGGER.trace("Before commit..."); + session.getTransaction().commit(); + LOGGER.trace("Committed!"); + } catch (ObjectNotFoundException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (SchemaException ex) { + transactionHelper.rollbackTransaction(session, ex, result, true); + throw ex; + } catch (QueryException | DtoTranslationException | RuntimeException ex) { + transactionHelper.handleGeneralException(ex, session, result); // should always throw an exception + throw new SystemException("Exception " + ex + " was not handled correctly", ex); // ...so this shouldn't occur at all + } finally { + transactionHelper.cleanupSessionAndResult(session, result); + LOGGER.trace("Session cleaned up."); + } + } +} diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/TransactionHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/TransactionHelper.java new file mode 100644 index 00000000000..8038cabef85 --- /dev/null +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/TransactionHelper.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql.helpers; + +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.hibernate.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.sql.SQLException; + +/** + * @author mederly + */ +@Component +public class TransactionHelper { + + private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); + private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(SqlRepositoryServiceImpl.PERFORMANCE_LOG_NAME); + + @Autowired + @Qualifier("repositoryService") + private RepositoryService repositoryService; + + private SqlRepositoryServiceImpl getSqlRepo() { + return (SqlRepositoryServiceImpl) repositoryService; + } + + public Session beginReadOnlyTransaction() { + return beginTransaction(getSqlRepo().getConfiguration().isUseReadOnlyTransactions()); + } + + public Session beginTransaction() { + return beginTransaction(false); + } + + public Session beginTransaction(boolean readOnly) { + return getSqlRepo().beginTransaction(readOnly); + } + + public void rollbackTransaction(Session session, Exception ex, OperationResult result, boolean fatal) { + getSqlRepo().rollbackTransaction(session, ex, result, fatal); + } + + public void rollbackTransaction(Session session, Exception ex, String message, OperationResult result, boolean fatal) { + getSqlRepo().rollbackTransaction(session, ex, message, result, fatal); + } + + public void rollbackTransaction(Session session) { + getSqlRepo().rollbackTransaction(session); + } + + public void cleanupSessionAndResult(Session session, OperationResult result) { + getSqlRepo().cleanupSessionAndResult(session, result); + } + + public void handleGeneralException(Exception ex, Session session, OperationResult result) { + getSqlRepo().handleGeneralException(ex, session, result); + } + + public void handleGeneralRuntimeException(RuntimeException ex, Session session, OperationResult result) { + getSqlRepo().handleGeneralRuntimeException(ex, session, result); + } + + public void handleGeneralCheckedException(Exception ex, Session session, OperationResult result) { + getSqlRepo().handleGeneralCheckedException(ex, session, result); + } + + public SQLException findSqlException(Throwable ex) { + return getSqlRepo().findSqlException(ex); + } +} \ No newline at end of file diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java index aff1ae533c0..72a9304c21e 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query/QueryInterpreter.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.sql.ObjectPagingAfterOid; import com.evolveum.midpoint.repo.sql.SqlRepositoryConfiguration; import com.evolveum.midpoint.repo.sql.query.definition.Definition; import com.evolveum.midpoint.repo.sql.query.definition.EntityDefinition; @@ -52,8 +53,6 @@ import java.lang.reflect.Modifier; import java.util.*; -import static com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl.*; - /** * @author lazyman */ diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java index efaee739bce..230f89fb4ed 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/QueryInterpreter2.java @@ -80,7 +80,7 @@ import java.util.HashMap; import java.util.Map; -import static com.evolveum.midpoint.repo.sql.SqlRepositoryServiceImpl.ObjectPagingAfterOid; +import com.evolveum.midpoint.repo.sql.ObjectPagingAfterOid; /** * Interprets midPoint queries by translating them to hibernate (HQL) ones. From eadce8e8a0ecdbef88e908ae82545feb11043696 Mon Sep 17 00:00:00 2001 From: honchar Date: Tue, 8 Dec 2015 11:23:45 +0100 Subject: [PATCH 076/116] Associations editable panel: new class is created for associations choose panel --- .../web/component/form/ValueChoosePanel.java | 479 ++++++++---------- .../web/component/prism/PrismValuePanel.java | 39 +- .../AssociationValueChoosePanel.html | 35 ++ .../AssociationValueChoosePanel.java | 354 +++++++++++++ 4 files changed, 623 insertions(+), 284 deletions(-) create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java index 827b4b42823..393052cedd3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/form/ValueChoosePanel.java @@ -1,16 +1,10 @@ package com.evolveum.midpoint.web.component.form; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPage; import com.evolveum.midpoint.web.util.WebMiscUtil; -import javafx.beans.property.ObjectProperty; import org.apache.wicket.Page; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -43,190 +37,168 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -public class ValueChoosePanel extends SimplePanel { +public class ValueChoosePanel extends SimplePanel { - private static final Trace LOGGER = TraceManager.getTrace(MultiValueChoosePanel.class); + private static final Trace LOGGER = TraceManager.getTrace(MultiValueChoosePanel.class); - private static final String ID_LABEL = "label"; + private static final String ID_LABEL = "label"; - private static final String ID_TEXT_WRAPPER = "textWrapper"; - private static final String ID_TEXT = "text"; - private static final String ID_FEEDBACK = "feedback"; - private static final String ID_ADD = "add"; - private static final String ID_REMOVE = "remove"; - private static final String ID_BUTTON_GROUP = "buttonGroup"; - private static final String ID_EDIT = "edit"; + private static final String ID_TEXT_WRAPPER = "textWrapper"; + private static final String ID_TEXT = "text"; + private static final String ID_FEEDBACK = "feedback"; + private static final String ID_ADD = "add"; + private static final String ID_REMOVE = "remove"; + private static final String ID_BUTTON_GROUP = "buttonGroup"; + private static final String ID_EDIT = "edit"; - protected static final String MODAL_ID_OBJECT_SELECTION_POPUP = "objectSelectionPopup"; + protected static final String MODAL_ID_OBJECT_SELECTION_POPUP = "objectSelectionPopup"; - private static final String CLASS_MULTI_VALUE = "multivalue-form"; - - private Collection> options = null; + private static final String CLASS_MULTI_VALUE = "multivalue-form"; public ValueChoosePanel(String id, IModel value, List values, boolean required, Class type) { - this(id, value, values, required, type, null, null); - } - - public ValueChoosePanel(String id, IModel value, List values, boolean required, Class type, - ObjectQuery query, Collection> options){ super(id, value); setOutputMarkupId(true); - this.options = options; - initLayout(value, values, required, type, query); + + initLayout(value, values, required, type); } - private void initLayout(final IModel value, final List values, - final boolean required, Class type, ObjectQuery query) { + private void initLayout(final IModel value, final List values, final boolean required, Class type) { + + + WebMarkupContainer textWrapper = new WebMarkupContainer(ID_TEXT_WRAPPER); - - WebMarkupContainer textWrapper = new WebMarkupContainer(ID_TEXT_WRAPPER); + textWrapper.setOutputMarkupId(true); - textWrapper.setOutputMarkupId(true); + TextField text = new TextField<>(ID_TEXT, createTextModel(value)); + text.add(new AjaxFormComponentUpdatingBehavior("onblur") { + @Override + protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { + } + }); + text.setRequired(required); + text.setEnabled(false); + textWrapper.add(text); - TextField text = new TextField<>(ID_TEXT, createTextModel(value)); - text.add(new AjaxFormComponentUpdatingBehavior("onblur") { - @Override - protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { - } - }); - text.setRequired(required); - text.setEnabled(false); - textWrapper.add(text); + FeedbackPanel feedback = new FeedbackPanel(ID_FEEDBACK, new ComponentFeedbackMessageFilter(text)); + textWrapper.add(feedback); - FeedbackPanel feedback = new FeedbackPanel(ID_FEEDBACK, new ComponentFeedbackMessageFilter(text)); - textWrapper.add(feedback); + AjaxLink edit = new AjaxLink(ID_EDIT) { - AjaxLink edit = new AjaxLink(ID_EDIT) { + @Override + public void onClick(AjaxRequestTarget target) { + editValuePerformed(values, target); + } + }; + textWrapper.add(edit); + add(textWrapper); - @Override - public void onClick(AjaxRequestTarget target) { - editValuePerformed(values, target); - } - }; - textWrapper.add(edit); - add(textWrapper); + initDialog(type, values); - initDialog(type, values, query); + } - } - // protected T createNewEmptyItem() throws InstantiationException, IllegalAccessException { // return ty; // } - - protected void replaceIfEmpty(Object object) { - T old = getModelObject(); - ObjectReferenceType ort = ObjectTypeUtil.createObjectRef((ObjectType) object); - ort.setTargetName(((ObjectType) object).getName()); - if (old instanceof PrismPropertyValue) { // let's assume we are working with associations panel -// ObjectType newValue= (ObjectType)object; -// getModel().setObject((T)newValue); - //TODO - getModel().setObject((T) ort.asReferenceValue()); - } else { - getModel().setObject((T) ort.asReferenceValue()); - } - } - - protected void initDialog(final Class type, List values, ObjectQuery query) { - - if (FocusType.class.equals(type)){ - initUserOrgDialog(); - } else { - initGenericDialog(type, values, query); - } - } - - // for ModalWindow treatment see comments in ChooseTypePanel - private void initGenericDialog(final Class type, final List values, final ObjectQuery query) { - final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); - - ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { - - // See analogous discussion in ChooseTypePanel - public ValueChoosePanel getRealParent() { - return WebMiscUtil.theSameForPage(ValueChoosePanel.this, getCallingPageReference()); - } - - @Override - public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object) { - getRealParent().choosePerformed(target, object); - } + + protected void replaceIfEmpty(Object object) { + boolean added = false; + ObjectReferenceType ort = ObjectTypeUtil.createObjectRef((ObjectType) object); + ort.setTargetName(((ObjectType) object).getName()); + getModel().setObject((T) ort.asReferenceValue()); + + } + + protected void initDialog(final Class type, List values) { + + if (FocusType.class.equals(type)) { + initUserOrgDialog(); + } else { + initGenericDialog(type, values); + + + } + } + + // for ModalWindow treatment see comments in ChooseTypePanel + private void initGenericDialog(final Class type, final List values) { + final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); + + ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { + + // See analogous discussion in ChooseTypePanel + public ValueChoosePanel getRealParent() { + return WebMiscUtil.theSameForPage(ValueChoosePanel.this, getCallingPageReference()); + } @Override - public Collection> getDataProviderOptions(){ - return options; + public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object) { + getRealParent().choosePerformed(target, object); } - @Override - public ObjectQuery getDataProviderQuery() { - if (query != null){ - return query; - } else { - return getRealParent().createChooseQuery(values); - } - } - - @Override - public boolean isSearchEnabled() { - //TODO don't commit - return false; - } - - @Override - public Class getObjectTypeClass() { - return type; - } - - }; - - ObjectSelectionPage.prepareDialog(dialog, context, this, "chooseTypeDialog.title", ID_TEXT_WRAPPER); - add(dialog); - } - - - private void initUserOrgDialog() { - final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); - ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { - - // See analogous discussion in ChooseTypePanel - public ValueChoosePanel getRealParent() { - return WebMiscUtil.theSameForPage(ValueChoosePanel.this, getCallingPageReference()); - } - - @Override - public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object) { - getRealParent().choosePerformed(target, object); - } - - @Override - public boolean isSearchEnabled() { - return true; - } - - @Override - public Class getObjectTypeClass() { - return UserType.class; - } - - @Override - protected WebMarkupContainer createExtraContentContainer(String extraContentId, final ObjectSelectionPanel objectSelectionPanel) { - return new UserOrgReferenceChoosePanel(extraContentId, Boolean.FALSE) { - @Override - protected void onReferenceTypeChangePerformed(AjaxRequestTarget target, Boolean newValue) { - objectSelectionPanel.updateTableByTypePerformed(target, Boolean.FALSE.equals(newValue) ? UserType.class : OrgType.class); - } - }; - } - }; - - ObjectSelectionPage.prepareDialog(dialog, context, this, "chooseTypeDialog.title", ID_TEXT_WRAPPER); - add(dialog); - } - - protected ObjectQuery createChooseQuery(List values) { - ArrayList oidList = new ArrayList<>(); - ObjectQuery query = new ObjectQuery(); + @Override + public ObjectQuery getDataProviderQuery() { + return getRealParent().createChooseQuery(values); + } + + @Override + public boolean isSearchEnabled() { + return true; + } + + @Override + public Class getObjectTypeClass() { + return type; + } + + }; + + ObjectSelectionPage.prepareDialog(dialog, context, this, "chooseTypeDialog.title", ID_TEXT_WRAPPER); + add(dialog); + } + + + private void initUserOrgDialog() { + final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); + ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { + + // See analogous discussion in ChooseTypePanel + public ValueChoosePanel getRealParent() { + return WebMiscUtil.theSameForPage(ValueChoosePanel.this, getCallingPageReference()); + } + + @Override + public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object) { + getRealParent().choosePerformed(target, object); + } + + @Override + public boolean isSearchEnabled() { + return true; + } + + @Override + public Class getObjectTypeClass() { + return UserType.class; + } + + @Override + protected WebMarkupContainer createExtraContentContainer(String extraContentId, final ObjectSelectionPanel objectSelectionPanel) { + return new UserOrgReferenceChoosePanel(extraContentId, Boolean.FALSE) { + @Override + protected void onReferenceTypeChangePerformed(AjaxRequestTarget target, Boolean newValue) { + objectSelectionPanel.updateTableByTypePerformed(target, Boolean.FALSE.equals(newValue) ? UserType.class : OrgType.class); + } + }; + } + }; + + ObjectSelectionPage.prepareDialog(dialog, context, this, "chooseTypeDialog.title", ID_TEXT_WRAPPER); + add(dialog); + } + + protected ObjectQuery createChooseQuery(List values) { + ArrayList oidList = new ArrayList<>(); + ObjectQuery query = new ObjectQuery(); //TODO we should add to filter currently displayed value //not to be displayed on ObjectSelectionPanel instead of saved value // for (PrismReferenceValue ref : values) { @@ -241,103 +213,94 @@ protected ObjectQuery createChooseQuery(List values) { // oidList.add(orgModel.getObject().getObject().asObjectable().getOid()); // } - if (oidList.isEmpty()) { - return null; - } - - ObjectFilter oidFilter = InOidFilter.createInOid(oidList); - query.setFilter(NotFilter.createNot(oidFilter)); - - return query; - } - - /** - * @return css class for off-setting other values (not first, left to the - * first there is a label) - */ - protected String getOffsetClass() { - return "col-md-offset-4"; - } - - protected IModel createTextModel(final IModel model) { - return new AbstractReadOnlyModel() { - - @Override - public String getObject() { - T ort = (T) model.getObject(); - - if (ort instanceof PrismReferenceValue){ - PrismReferenceValue prv = (PrismReferenceValue) ort; - return prv == null ? null : (prv.getTargetName() != null ? prv.getTargetName().getOrig() : prv.getOid()); - } else if (ort instanceof ObjectViewDto) { - return ((ObjectViewDto) ort).getName(); - } - return ort.toString(); - - } - }; - } - - protected void editValuePerformed(List values, AjaxRequestTarget target) { - ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); - window.show(target); - ObjectSelectionPanel dialog = (ObjectSelectionPanel) window.get(createComponentPath(window.getContentId(), ObjectSelectionPage.ID_OBJECT_SELECTION_PANEL)); - if (dialog != null) { - dialog.updateTablePerformed(target, createChooseQuery(values)); - } - } - - /* - * TODO - this method contains check, if chosen object already is not in - * selected values array This is a temporary solution until we well be able - * to create "already-chosen" query - */ - protected void choosePerformed(AjaxRequestTarget target, C object) { - choosePerformedHook(target, object); - ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); - window.close(target); - - if(isObjectUnique(object)){ - replaceIfEmpty(object); - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("New object instance has been added to the model."); - } - // has to be done in the context of parent page - //target.add(this); - } - - - protected boolean isObjectUnique(C object) { - - // for(T o: ){ - T old = getModelObject(); - if (old instanceof PrismPropertyValue){ - if (old == null || ((PrismPropertyValue)old).isEmpty()){ - return true; - } - if (((PrismPropertyValue)old).getValue().equals(object.asPrismObject().getValue())) { - return false; - } - } else { - if (old == null || ((PrismReferenceValue)old).isEmpty()){ - return true; + if (oidList.isEmpty()) { + return null; + } + + ObjectFilter oidFilter = InOidFilter.createInOid(oidList); + query.setFilter(NotFilter.createNot(oidFilter)); + + return query; + } + + /** + * @return css class for off-setting other values (not first, left to the + * first there is a label) + */ + protected String getOffsetClass() { + return "col-md-offset-4"; + } + + protected IModel createTextModel(final IModel model) { + return new AbstractReadOnlyModel() { + + @Override + public String getObject() { + T ort = (T) model.getObject(); + + if (ort instanceof PrismReferenceValue) { + PrismReferenceValue prv = (PrismReferenceValue) ort; + return prv == null ? null : (prv.getTargetName() != null ? prv.getTargetName().getOrig() : prv.getOid()); + } else if (ort instanceof ObjectViewDto) { + return ((ObjectViewDto) ort).getName(); + } + return ort.toString(); + } - if (((PrismReferenceValue)old).getOid().equals(object.getOid())) { - return false; - }} + }; + } + + protected void editValuePerformed(List values, AjaxRequestTarget target) { + ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); + window.show(target); + ObjectSelectionPanel dialog = (ObjectSelectionPanel) window.get(createComponentPath(window.getContentId(), ObjectSelectionPage.ID_OBJECT_SELECTION_PANEL)); + if (dialog != null) { + dialog.updateTablePerformed(target, createChooseQuery(values)); + } + } + + /* + * TODO - this method contains check, if chosen object already is not in + * selected values array This is a temporary solution until we well be able + * to create "already-chosen" query + */ + protected void choosePerformed(AjaxRequestTarget target, C object) { + choosePerformedHook(target, object); + ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); + window.close(target); + + if (isObjectUnique(object)) { + replaceIfEmpty(object); + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("New object instance has been added to the model."); + } + // has to be done in the context of parent page + //target.add(this); + } + - // } - return true; - } + protected boolean isObjectUnique(C object) { + // for(T o: ){ + PrismReferenceValue old = (PrismReferenceValue) getModelObject(); + if (old == null || old.isEmpty()) { + return true; + } + if (old.getOid().equals(object.getOid())) { + return false; + } + // } + return true; + } - /** - * A custom code in form of hook that can be run on event of choosing new - * object with this chooser component - * */ - protected void choosePerformedHook(AjaxRequestTarget target, C object) { - } + + /** + * A custom code in form of hook that can be run on event of choosing new + * object with this chooser component + */ + protected void choosePerformedHook(AjaxRequestTarget target, C object) { + } } \ No newline at end of file diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index 20023d5f2d2..d88e08c4b0c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -35,6 +35,7 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.page.admin.PageAdminFocus; +import com.evolveum.midpoint.web.page.admin.users.component.AssociationValueChoosePanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.Validate; @@ -283,7 +284,7 @@ private boolean isRemoveButtonVisible() { return false; } Component inputPanel = this.get(ID_VALUE_CONTAINER).get(ID_INPUT); - if (inputPanel instanceof ValueChoosePanel){ + if (inputPanel instanceof ValueChoosePanel || inputPanel instanceof AssociationValueChoosePanel){ return true; } @@ -413,6 +414,14 @@ private Panel createTypedInputComponent(String id) { ContainerWrapper containerWrapper = itemWrapper.getContainer(); if(containerWrapper != null && containerWrapper.getPath() != null){ if(ShadowType.F_ASSOCIATION.getLocalPart().equals(containerWrapper.getPath().toString())){ + + + + + + + + PrismContext prismContext = item.getPrismContext(); if (prismContext == null) { prismContext = pageBase.getPrismContext(); @@ -425,10 +434,10 @@ private Panel createTypedInputComponent(String id) { PrismObject resource = ((ShadowType)containerWrapper.getObject().getObject().asObjectable()).getResource().asPrismObject(); ObjectQuery query = getAssociationsSearchQuery(prismContext, resource, objectClassItem, kindItem, intentItem); - List> values = loadAssociationShadows(query); - return new ValueChoosePanel(id, - new PropertyModel<>(model, "value"), item.getValues(), false, ShadowType.class, query, getAssociationsSearchOptions()); + PropertyModel propertyModel = new PropertyModel<>(model, "value"); +List values = item.getValues(); + return new AssociationValueChoosePanel(id, propertyModel, values, false, ShadowType.class, query); } } @@ -791,27 +800,5 @@ private ObjectQuery getAssociationsSearchQuery(PrismContext prismContext, PrismO } - private List> loadAssociationShadows(ObjectQuery query) { - Task task = pageBase.createSimpleTask(OPERATION_LOAD_ASSOC_SHADOWS); - OperationResult result = new OperationResult(OPERATION_LOAD_ASSOC_SHADOWS); - - List> assocShadows = null; - try { - assocShadows = pageBase.getModelService().searchObjects(ShadowType.class, query, getAssociationsSearchOptions(), task, result); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "Unable to load association shadow", ex); - result.recordFatalError("Unable to load association shadow", ex); - } finally { - result.computeStatus(); - } - return assocShadows; - } - - private Collection> getAssociationsSearchOptions(){ - Collection> options = new ArrayList>(); - options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createRaw())); - options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createNoFetch())); - return options; - } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html new file mode 100644 index 00000000000..1d66d1b607a --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html @@ -0,0 +1,35 @@ + + + + + +
+ +
+
+ + + + + +
+
+ + + \ No newline at end of file diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java new file mode 100644 index 00000000000..a7813ee8cd6 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java @@ -0,0 +1,354 @@ +package com.evolveum.midpoint.web.page.admin.users.component; + +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.InOidFilter; +import com.evolveum.midpoint.prism.query.NotFilter; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.util.SimplePanel; +import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPage; +import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPanel; +import com.evolveum.midpoint.web.page.admin.dto.ObjectViewDto; +import com.evolveum.midpoint.web.page.admin.roles.component.UserOrgReferenceChoosePanel; +import com.evolveum.midpoint.web.util.WebMiscUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.panel.FeedbackPanel; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.IModel; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Created by Kate Honchar + * + */ + //TODO the class is created as a copy of ValueChoosePanel but + //with the possibility to work with PrismPropertyValue objects + // (for now ValueChoosePanel works only with PrismReferenceValue); + //in future some super class is to be created to union the common + // functionality of these 2 classes +public class AssociationValueChoosePanel extends SimplePanel { + + private static final Trace LOGGER = TraceManager.getTrace(AssociationValueChoosePanel.class); + + private static final String ID_LABEL = "label"; + + private static final String ID_TEXT_WRAPPER = "textWrapper"; + private static final String ID_TEXT = "text"; + private static final String ID_FEEDBACK = "feedback"; + private static final String ID_ADD = "add"; + private static final String ID_REMOVE = "remove"; + private static final String ID_BUTTON_GROUP = "buttonGroup"; + private static final String ID_EDIT = "edit"; + + protected static final String MODAL_ID_OBJECT_SELECTION_POPUP = "objectSelectionPopup"; + + + private ObjectQuery query = null; + + public AssociationValueChoosePanel(String id, IModel value, List values, boolean required, Class type, + ObjectQuery query){ + super(id, value); + this.query = query; + setOutputMarkupId(true); + initLayout(value, values, required, type); + } + + private void initLayout(final IModel value, final List values, + final boolean required, Class type) { + + + WebMarkupContainer textWrapper = new WebMarkupContainer(ID_TEXT_WRAPPER); + + textWrapper.setOutputMarkupId(true); + + TextField text = new TextField<>(ID_TEXT, createTextModel(value)); + text.add(new AjaxFormComponentUpdatingBehavior("onblur") { + @Override + protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { + } + }); + text.setRequired(required); + text.setEnabled(false); + textWrapper.add(text); + + FeedbackPanel feedback = new FeedbackPanel(ID_FEEDBACK, new ComponentFeedbackMessageFilter(text)); + textWrapper.add(feedback); + + AjaxLink edit = new AjaxLink(ID_EDIT) { + + @Override + public void onClick(AjaxRequestTarget target) { + editValuePerformed(values, target); + } + }; + textWrapper.add(edit); + add(textWrapper); + + initDialog(type, values); + + } + +// protected T createNewEmptyItem() throws InstantiationException, IllegalAccessException { +// return ty; +// } + + protected void replaceIfEmpty(Object object) { + T old = getModelObject(); + ObjectReferenceType ort = ObjectTypeUtil.createObjectRef((ObjectType) object); + ort.setTargetName(((ObjectType) object).getName()); + if (old instanceof PrismPropertyValue) { // let's assume we are working with associations panel + IModel modelT = getModel(); + T objectT = modelT.getObject(); + if (objectT == null){ + + } + + ShadowType shadowType = (ShadowType) object; + + PrismProperty newValue = (PrismProperty)shadowType.asPrismObject().getValue().getItems().get(0); + PrismPropertyValue ppv = (PrismPropertyValue)newValue.getValues().get(0); + //TODO + getModel().setObject((T)ppv); + } else { + getModel().setObject((T) ort.asReferenceValue()); + } + } + + protected void initDialog(final Class type, List values) { + + if (FocusType.class.equals(type)){ + initUserOrgDialog(); + } else { + initGenericDialog(type, values); + } + } + + // for ModalWindow treatment see comments in ChooseTypePanel + private void initGenericDialog(final Class type, final List values) { + final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); + + ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { + + // See analogous discussion in ChooseTypePanel + public AssociationValueChoosePanel getRealParent() { + return WebMiscUtil.theSameForPage(AssociationValueChoosePanel.this, getCallingPageReference()); + } + + @Override + public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object) { + getRealParent().choosePerformed(target, object); + } + + @Override + public Collection> getDataProviderOptions(){ + return getAssociationsSearchOptions(); + } + + @Override + public ObjectQuery getDataProviderQuery() { + + return getRealParent().createChooseQuery(values); + } + + @Override + public boolean isSearchEnabled() { + //TODO don't commit + return false; + } + + @Override + public Class getObjectTypeClass() { + return type; + } + + }; + + ObjectSelectionPage.prepareDialog(dialog, context, this, "chooseTypeDialog.title", ID_TEXT_WRAPPER); + add(dialog); + } + + + private void initUserOrgDialog() { + final ModalWindow dialog = new ModalWindow(MODAL_ID_OBJECT_SELECTION_POPUP); + ObjectSelectionPanel.Context context = new ObjectSelectionPanel.Context(this) { + + // See analogous discussion in ChooseTypePanel + public AssociationValueChoosePanel getRealParent() { + return WebMiscUtil.theSameForPage(AssociationValueChoosePanel.this, getCallingPageReference()); + } + + @Override + public void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object) { + getRealParent().choosePerformed(target, object); + } + + @Override + public boolean isSearchEnabled() { + return true; + } + + @Override + public Class getObjectTypeClass() { + return UserType.class; + } + + @Override + protected WebMarkupContainer createExtraContentContainer(String extraContentId, final ObjectSelectionPanel objectSelectionPanel) { + return new UserOrgReferenceChoosePanel(extraContentId, Boolean.FALSE) { + @Override + protected void onReferenceTypeChangePerformed(AjaxRequestTarget target, Boolean newValue) { + objectSelectionPanel.updateTableByTypePerformed(target, Boolean.FALSE.equals(newValue) ? UserType.class : OrgType.class); + } + }; + } + }; + + ObjectSelectionPage.prepareDialog(dialog, context, this, "chooseTypeDialog.title", ID_TEXT_WRAPPER); + add(dialog); + } + + protected ObjectQuery createChooseQuery(List values) { + ArrayList oidList = new ArrayList<>(); + ObjectQuery query = new ObjectQuery(); +//TODO we should add to filter currently displayed value +//not to be displayed on ObjectSelectionPanel instead of saved value +// for (PrismReferenceValue ref : values) { +// if (ref != null) { +// if (ref.getOid() != null && !ref.getOid().isEmpty()) { +// oidList.add(ref.getOid()); +// } +// } +// } + +// if (isediting) { +// oidList.add(orgModel.getObject().getObject().asObjectable().getOid()); +// } + + if (oidList.isEmpty()) { + return null; + } + + ObjectFilter oidFilter = InOidFilter.createInOid(oidList); + query.setFilter(NotFilter.createNot(oidFilter)); + + return query; + } + + /** + * @return css class for off-setting other values (not first, left to the + * first there is a label) + */ + protected String getOffsetClass() { + return "col-md-offset-4"; + } + + protected IModel createTextModel(final IModel model) { + return new AbstractReadOnlyModel() { + + @Override + public String getObject() { + T ort = (T) model.getObject(); + + if (ort instanceof PrismReferenceValue){ + PrismReferenceValue prv = (PrismReferenceValue) ort; + return prv == null ? null : (prv.getTargetName() != null ? prv.getTargetName().getOrig() : prv.getOid()); + } else if (ort instanceof ObjectViewDto) { + return ((ObjectViewDto) ort).getName(); + } + return ort.toString(); + + } + }; + } + + protected void editValuePerformed(List values, AjaxRequestTarget target) { + ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); + window.show(target); + ObjectSelectionPanel dialog = (ObjectSelectionPanel) window.get(createComponentPath(window.getContentId(), ObjectSelectionPage.ID_OBJECT_SELECTION_PANEL)); + if (dialog != null) { + dialog.updateTablePerformed(target, createChooseQuery(values)); + } + } + + /* + * TODO - this method contains check, if chosen object already is not in + * selected values array This is a temporary solution until we well be able + * to create "already-chosen" query + */ + protected void choosePerformed(AjaxRequestTarget target, C object) { + choosePerformedHook(target, object); + ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); + window.close(target); + + if(isObjectUnique(object)){ + replaceIfEmpty(object); + } + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("New object instance has been added to the model."); + } + // has to be done in the context of parent page + //target.add(this); + } + + + protected boolean isObjectUnique(C object) { + + // for(T o: ){ + T old = getModelObject(); + if (old instanceof PrismPropertyValue){ + if (old == null || ((PrismPropertyValue)old).isEmpty()){ + return true; + } + if (((PrismPropertyValue)old).getValue().equals(object.asPrismObject().getValue())) { + return false; + } + } else { + if (old == null || ((PrismReferenceValue)old).isEmpty()){ + return true; + } + if (((PrismReferenceValue)old).getOid().equals(object.getOid())) { + return false; + }} + + // } + return true; + } + + + /** + * A custom code in form of hook that can be run on event of choosing new + * object with this chooser component + * */ + protected void choosePerformedHook(AjaxRequestTarget target, C object) { + } + + private Collection> getAssociationsSearchOptions() { + Collection> options = new ArrayList>(); + options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createRaw())); + options.add(SelectorOptions.create(ItemPath.EMPTY_PATH, GetOperationOptions.createNoFetch())); + return options; + } + + //TODO move query creating code from PrismValuePanel + private ObjectQuery getAssociationsSearchQuery() { + return new ObjectQuery(); + } + +} \ No newline at end of file From 71d49c9f7cb2e9a3aa784d5207367714ad50449d Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 8 Dec 2015 12:39:04 +0100 Subject: [PATCH 077/116] Fixing "campaign delete" problem. Added objectDelta to script variables when evaluating scripts in workflow module. --- .../midpoint/prism/util/PrismAsserts.java | 4 +- ...InitializeLoopThroughApproversInLevel.java | 12 +- .../midpoint/repo/sql/CertificationTest.java | 105 ++++++++ .../test/resources/cert/cert-campaign-1.xml | 252 ++++++++++++++++++ .../src/test/resources/logback-test.xml | 2 +- .../repo-sql-impl-test/testng-integration.xml | 1 + .../repo/sql/data/common/RObject.java | 4 + .../sql/helpers/CertificationCaseHelper.java | 34 ++- .../repo/sql/helpers/ObjectUpdater.java | 10 +- 9 files changed, 404 insertions(+), 20 deletions(-) create mode 100644 repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java create mode 100644 repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismAsserts.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismAsserts.java index 65fe2c62759..9a7234e1148 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismAsserts.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismAsserts.java @@ -684,9 +684,7 @@ public static void assertEquals(String message, PrismObje if (delta.isEmpty()) { suffix += ": Empty delta. The difference is most likely in meta-data"; } - LOGGER.error("ASSERT: {}: {} and {} not equals, delta:\n{}", new Object[]{ - message, expected, actual, delta.debugDump() - }); + LOGGER.error("ASSERT: {}: {} and {} not equals, delta:\n{}", message, expected, actual, delta.debugDump()); assert false: message + ": " + suffix; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java index a22439905a5..c195fdf1016 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.model.common.expression.ExpressionFactory; import com.evolveum.midpoint.model.common.expression.ExpressionVariables; import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.constants.SchemaConstants; @@ -45,6 +46,7 @@ import org.activiti.engine.delegate.JavaDelegate; import org.apache.commons.lang.Validate; +import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import java.util.*; @@ -228,7 +230,15 @@ private ExpressionVariables getDefaultVariables(DelegateExecution execution, Ope } } - // todo object delta, etc + ObjectDelta objectDelta = null; + try { + objectDelta = miscDataUtil.getObjectDelta(execution.getVariables(), true); + } catch (JAXBException e) { + throw new SchemaException("Couldn't get object delta: " + e.getMessage(), e); + } + variables.addVariableDefinition(SchemaConstants.T_OBJECT_DELTA, objectDelta); + + // todo other variables? return variables; } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java new file mode 100644 index 00000000000..20ac521090d --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.repo.api.RepoAddOptions; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.RetrieveOption; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.io.File; +import java.util.Arrays; + +import static com.evolveum.midpoint.schema.RetrieveOption.INCLUDE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_CASE; + +/** + * @author lazyman + */ +@ContextConfiguration(locations = {"../../../../../ctx-test.xml"}) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +public class CertificationTest extends BaseSQLRepoTest { + + private static final Trace LOGGER = TraceManager.getTrace(CertificationTest.class); + private static final File TEST_DIR = new File("src/test/resources/cert"); + + private String campaignOid; + + @Test + public void test100AddCampaignNonOverwrite() throws Exception { + PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + OperationResult result = new OperationResult("test100AddCampaignNonOverwrite"); + + campaignOid = repositoryService.addObject(campaign, null, result); + + result.recomputeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + + // rereading, as repo strips cases from the campaign (!) + PrismObject expected = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + checkCampaign(campaignOid, expected, result); + } + + private void checkCampaign(String campaignOid, PrismObject expectedObject, OperationResult result) throws SchemaException, ObjectNotFoundException { + SelectorOptions retrieve = SelectorOptions.create(F_CASE, GetOperationOptions.createRetrieve(INCLUDE)); + PrismObject campaign = repositoryService.getObject(AccessCertificationCampaignType.class, campaignOid, Arrays.asList(retrieve), result); + expectedObject.setOid(campaignOid); + PrismAsserts.assertEquivalent("Campaign is not as expected", expectedObject, campaign); + } + + @Test(expectedExceptions = ObjectAlreadyExistsException.class) + public void test105AddCampaignNonOverwriteExisting() throws Exception { + PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + OperationResult result = new OperationResult("test105AddCampaignNonOverwriteExisting"); + repositoryService.addObject(campaign, null, result); + } + + @Test + public void test108AddCampaignOverwriteExisting() throws Exception { + PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + OperationResult result = new OperationResult("test108AddCampaignOverwriteExisting"); + campaignOid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); + + // rereading, as repo strips cases from the campaign (!) + PrismObject expected = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + checkCampaign(campaignOid, expected, result); + } + + + + @Test + public void test900DeleteCampaign() throws Exception { + OperationResult result = new OperationResult("test900DeleteCampaign"); + repositoryService.deleteObject(AccessCertificationCampaignType.class, campaignOid, result); + result.recomputeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + } +} diff --git a/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml b/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml new file mode 100644 index 00000000000..0428c201a16 --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml @@ -0,0 +1,252 @@ + + + + + All user assignments 1 + Certifies all users' assignments. Everything is certified by the administrator. + + 2015-12-18T23:59:59.999+01:00 + http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage/handler-3 + + + 2015-12-16T23:59:59.999+01:00 + http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage-approaching/handler-3 + + + + 2015-12-18T11:59:59.999+01:00 + http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage-approaching/handler-3 + + + + 2015-12-04T00:37:08.885+01:00 + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + + http://midpoint.evolveum.com/xml/ns/public/certification/handlers-3#direct-assignment + + + + + 1 + Administrator's review + In this stage, the administrator has to review all the assignments of all users. + 14 + 48 + 12 + true + + + + + 2015-12-04T00:38:03.031+01:00 + inReviewStage + 1 + + 1 + Administrator's review + In this stage, the administrator has to review all the assignments of all users. + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + notDecided + 2015-12-04T01:10:20.032+01:00 + + notDecided + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + accept + 2015-12-04T01:04:06.385+01:00 + + accept + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + noResponse + 2015-12-04T01:10:08.670+01:00 + + noResponse + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + revoke + 2015-12-04T01:10:13.814+01:00 + + revoke + 1 + + + + + ri:cn + + strong + + CN + + + + + ri:sn + + strong + + SN + + + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + revoke + 2015-12-04T01:10:14.614+01:00 + + revoke + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + reduce + 2015-12-04T01:10:15.375+01:00 + + reduce + 1 + + + + false + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + revoke + 2015-12-04T01:10:16.136+01:00 + + revoke + 1 + + + + false + + diff --git a/repo/repo-sql-impl-test/src/test/resources/logback-test.xml b/repo/repo-sql-impl-test/src/test/resources/logback-test.xml index 51f06856ad3..091533d3971 100644 --- a/repo/repo-sql-impl-test/src/test/resources/logback-test.xml +++ b/repo/repo-sql-impl-test/src/test/resources/logback-test.xml @@ -28,7 +28,7 @@ - + diff --git a/repo/repo-sql-impl-test/testng-integration.xml b/repo/repo-sql-impl-test/testng-integration.xml index e2cd0129f47..abdc1668a9e 100644 --- a/repo/repo-sql-impl-test/testng-integration.xml +++ b/repo/repo-sql-impl-test/testng-integration.xml @@ -41,6 +41,7 @@ + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index 2b1be53a240..dfc487b19bd 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -110,7 +110,11 @@ @NamedQuery(name = "delete.lookupTableDataRow", query = "delete RLookupTableRow r where r.ownerOid = :oid and r.id = :id"), @NamedQuery(name = "get.campaignCaseLastId", query = "select max(c.id) from RAccessCertificationCase c where c.ownerOid = :oid"), @NamedQuery(name = "delete.campaignCases", query = "delete RAccessCertificationCase c where c.ownerOid = :oid"), + @NamedQuery(name = "delete.campaignCasesDecisions", query = "delete RAccessCertificationDecision d where d.ownerOwnerOid = :oid"), + @NamedQuery(name = "delete.campaignCasesReferences", query = "delete RCertCaseReference r where r.ownerOid = :oid"), @NamedQuery(name = "delete.campaignCase", query = "delete RAccessCertificationCase c where c.ownerOid = :oid and c.id = :id"), + @NamedQuery(name = "delete.campaignCaseDecisions", query = "delete RAccessCertificationDecision d where d.ownerOwnerOid = :oid and d.ownerId = :id"), + @NamedQuery(name = "delete.campaignCaseReferences", query = "delete RCertCaseReference r where r.ownerOid = :oid and r.id = :id"), @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), @NamedQuery(name = "get.campaignCase", query = "select c.fullObject from RAccessCertificationCase c where c.ownerOid=:ownerOid and c.id=:id") }) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 97d0006648f..502a1fdc12f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -105,10 +105,18 @@ public void addCertificationCampaignCases(Session session, String campaignOid, C } public void deleteCertificationCampaignCases(Session session, String oid) { - Query query = session.getNamedQuery("delete.campaignCases"); - query.setParameter("oid", oid); - - query.executeUpdate(); + // TODO couldn't this cascading be done by hibernate itself? + Query deleteDecisions = session.getNamedQuery("delete.campaignCasesDecisions"); + deleteDecisions.setParameter("oid", oid); + deleteDecisions.executeUpdate(); + + Query deleteReferences = session.getNamedQuery("delete.campaignCasesReferences"); + deleteReferences.setParameter("oid", oid); + deleteReferences.executeUpdate(); + + Query deleteCases = session.getNamedQuery("delete.campaignCases"); + deleteCases.setParameter("oid", oid); + deleteCases.executeUpdate(); } public Collection filterCampaignCaseModifications(Class type, @@ -174,10 +182,20 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle throw new SchemaException("Couldn't delete certification case with null id"); } affectedIds.add(id); - Query query = session.getNamedQuery("delete.campaignCase"); - query.setString("oid", campaignOid); - query.setInteger("id", RUtil.toInteger(id)); - query.executeUpdate(); + // TODO couldn't this cascading be done by hibernate itself? + Integer integerCaseId = RUtil.toInteger(id); + Query deleteCaseDecisions = session.getNamedQuery("delete.campaignCaseDecisions"); + deleteCaseDecisions.setString("oid", campaignOid); + deleteCaseDecisions.setInteger("id", integerCaseId); + deleteCaseDecisions.executeUpdate(); + Query deleteCaseReferences = session.getNamedQuery("delete.campaignCaseReferences"); + deleteCaseReferences.setString("oid", campaignOid); + deleteCaseReferences.setInteger("id", integerCaseId); + deleteCaseReferences.executeUpdate(); + Query deleteCase = session.getNamedQuery("delete.campaignCase"); + deleteCase.setString("oid", campaignOid); + deleteCase.setInteger("id", integerCaseId); + deleteCase.executeUpdate(); } } if (delta.getValuesToAdd() != null) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java index e0a70115a48..9979604cd39 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -126,7 +126,7 @@ public String addObjectAttempt(PrismObject object, Rep RObject rObject = createDataObjectFromJAXB(object, operation); - session = beginTransaction(); + session = transactionHelper.beginTransaction(); closureContext = closureManager.onBeginTransactionAdd(session, object, options.isOverwrite()); @@ -171,10 +171,6 @@ public String addObjectAttempt(PrismObject object, Rep return oid; } - private Session beginTransaction() { - return transactionHelper.beginTransaction(); - } - private String overwriteAddObjectAttempt(PrismObject object, RObject rObject, String originalOid, Session session, OrgClosureManager.Context closureContext) throws ObjectAlreadyExistsException, SchemaException, DtoTranslationException { @@ -305,7 +301,7 @@ public void deleteObjectAttempt(Class type, String oid Session session = null; OrgClosureManager.Context closureContext = null; try { - session = beginTransaction(); + session = transactionHelper.beginTransaction(); closureContext = closureManager.onBeginTransactionDelete(session, type, oid); @@ -356,7 +352,7 @@ public void modifyObjectAttempt(Class type, String oid Session session = null; OrgClosureManager.Context closureContext = null; try { - session = beginTransaction(); + session = transactionHelper.beginTransaction(); closureContext = closureManager.onBeginTransactionModify(session, type, oid, modifications); From c250f24502d9f16d59161d8cf4750f3d5eed1192 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Nov 2015 14:05:19 +0100 Subject: [PATCH 078/116] Fixing the same problem in script for Oracle. (cherry picked from commit 3f27a39) --- config/sql/_all/oracle-3.3-all.sql | 2 +- config/sql/midpoint/3.3/oracle/oracle-3.3.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/sql/_all/oracle-3.3-all.sql b/config/sql/_all/oracle-3.3-all.sql index 492834906f3..6705f3dea6b 100644 --- a/config/sql/_all/oracle-3.3-all.sql +++ b/config/sql/_all/oracle-3.3-all.sql @@ -254,7 +254,7 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus NUMBER(10, 0), - hasPhoto NUMBER(1, 0) DEFAULT FALSE NOT NULL, + hasPhoto NUMBER(1, 0) DEFAULT 0 NOT NULL, oid VARCHAR2(36 CHAR) NOT NULL, PRIMARY KEY (oid) ) INITRANS 30; diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.3.sql b/config/sql/midpoint/3.3/oracle/oracle-3.3.sql index e2be7e3e7a7..67435c2acfb 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.3.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.3.sql @@ -254,7 +254,7 @@ CREATE TABLE m_focus ( validTo TIMESTAMP, validityChangeTimestamp TIMESTAMP, validityStatus NUMBER(10, 0), - hasPhoto NUMBER(1, 0) DEFAULT FALSE NOT NULL, + hasPhoto NUMBER(1, 0) DEFAULT 0 NOT NULL, oid VARCHAR2(36 CHAR) NOT NULL, PRIMARY KEY (oid) ) INITRANS 30; From dadba48ca0c3013993c62e3c52b69d64297a09e8 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 8 Dec 2015 15:50:36 +0100 Subject: [PATCH 079/116] Fixed NPE in "My cases to decide" page. --- .../evolveum/midpoint/repo/sql/AddGetObjectTest.java | 11 +++++++++++ .../evolveum/midpoint/repo/sql/CertificationTest.java | 9 +++++++++ .../common/container/RAccessCertificationCase.java | 2 +- .../midpoint/repo/sql/helpers/ObjectUpdater.java | 2 ++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java index 8f3a8960a73..dc91d350f1c 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java @@ -166,6 +166,11 @@ private void addGetCompare(File file) throws Exception { GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); } PrismObject newObject = repositoryService.getObject(clazz, oids.get(i), o, result); + + if (AccessCertificationCampaignType.class.equals(clazz)) { + removeCampaignRef((AccessCertificationCampaignType) (newObject.asObjectable())); + } + LOGGER.info("Old\n{}\nnew\n{}", new Object[]{object.debugDump(3), newObject.debugDump(3)}); checkContainersSize(newObject, object); System.out.println("OLD: " + object.findProperty(ObjectType.F_NAME).getValue()); @@ -203,6 +208,12 @@ private void addGetCompare(File file) throws Exception { AssertJUnit.assertEquals("Found changes during add/get test " + count, 0, count); } + private void removeCampaignRef(AccessCertificationCampaignType campaign) { + for (AccessCertificationCaseType aCase : campaign.getCase()) { + aCase.asPrismContainerValue().removeReference(AccessCertificationCaseType.F_CAMPAIGN_REF); + } + } + private Integer size(PrismContainerValue value) { if (value == null) { return null; diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java index 20ac521090d..84765f36d41 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java @@ -40,6 +40,7 @@ import static com.evolveum.midpoint.schema.RetrieveOption.INCLUDE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_CASE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CAMPAIGN_REF; /** * @author lazyman @@ -72,9 +73,16 @@ private void checkCampaign(String campaignOid, PrismObject retrieve = SelectorOptions.create(F_CASE, GetOperationOptions.createRetrieve(INCLUDE)); PrismObject campaign = repositoryService.getObject(AccessCertificationCampaignType.class, campaignOid, Arrays.asList(retrieve), result); expectedObject.setOid(campaignOid); + removeCampaignRef(campaign.asObjectable()); PrismAsserts.assertEquivalent("Campaign is not as expected", expectedObject, campaign); } + private void removeCampaignRef(AccessCertificationCampaignType campaign) { + for (AccessCertificationCaseType aCase : campaign.getCase()) { + aCase.asPrismContainerValue().removeReference(F_CAMPAIGN_REF); + } + } + @Test(expectedExceptions = ObjectAlreadyExistsException.class) public void test105AddCampaignNonOverwriteExisting() throws Exception { PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); @@ -86,6 +94,7 @@ public void test105AddCampaignNonOverwriteExisting() throws Exception { public void test108AddCampaignOverwriteExisting() throws Exception { PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); OperationResult result = new OperationResult("test108AddCampaignOverwriteExisting"); + campaign.setOid(campaignOid); // doesn't work without specifying OID campaignOid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); // rereading, as repo strips cases from the campaign (!) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 67c07403b61..c59032d1053 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -370,7 +370,7 @@ public static AccessCertificationCaseType createJaxb(byte[] fullObject, PrismCon throw e; } AccessCertificationCaseType aCase = caseContainer.getValue().asContainerable().clone(); // clone in order to make it parent-less - aCase.asPrismContainerValue().removeReference(AccessCertificationCaseType.F_CAMPAIGN_REF); + //aCase.asPrismContainerValue().removeReference(AccessCertificationCaseType.F_CAMPAIGN_REF); return aCase; } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java index 9979604cd39..8f5d780a584 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -185,6 +185,8 @@ private String overwriteAddObjectAttempt(PrismObject o ObjectDelta delta = object.diff(oldObject); modifications = delta.getModifications(); + LOGGER.trace("overwriteAddObjectAttempt: originalOid={}, modifications={}", originalOid, modifications); + //we found existing object which will be overwritten, therefore we increment version Integer version = RUtil.getIntegerFromString(oldObject.getVersion()); version = (version == null) ? 0 : ++version; From 5f9158b95fe55f646c7fefb2223426af06f6f696 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 9 Dec 2015 12:35:22 +0100 Subject: [PATCH 080/116] Delta builder. New tests and small fixes for repo cert support. --- .../prism/delta/builder/DeltaBuilder.java | 222 +++++++++++++++ .../prism/delta/builder/S_ItemEntry.java | 41 +++ .../prism/delta/builder/S_MaybeDelete.java | 27 ++ .../prism/delta/builder/S_ValuesEntry.java | 33 +++ .../midpoint/prism/path/ItemPath.java | 25 +- .../midpoint/repo/sql/CertificationTest.java | 260 ++++++++++++++++-- .../midpoint/repo/sql/LookupTableTest.java | 105 +++++++ .../test/resources/cert/cert-campaign-1.xml | 16 +- .../src/test/resources/logback-test.xml | 3 + .../src/test/resources/lookup/table-1.xml | 47 ++++ .../common/RAccessCertificationCampaign.java | 2 +- .../repo/sql/data/common/RObject.java | 3 +- .../common/container/RCertCaseReference.java | 4 +- .../sql/helpers/CertificationCaseHelper.java | 21 +- .../repo/sql/helpers/ObjectRetriever.java | 2 +- .../repo/sql/helpers/ObjectUpdater.java | 8 +- 16 files changed, 776 insertions(+), 43 deletions(-) create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_MaybeDelete.java create mode 100644 infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java create mode 100644 repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java create mode 100644 repo/repo-sql-impl-test/src/test/resources/lookup/table-1.xml diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java new file mode 100644 index 00000000000..514427a95cc --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.delta.builder; + +import com.evolveum.midpoint.prism.ComplexTypeDefinition; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismReferenceDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.delta.ReferenceDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.builder.R_Filter; +import com.evolveum.midpoint.prism.query.builder.S_FilterEntryOrEmpty; +import com.evolveum.midpoint.util.exception.SchemaException; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.List; + +/** + * Grammar: + * + * ObjectDelta ::= (ItemDelta)* ( 'OBJECT-DELTA(oid)' | 'ITEM-DELTA' | 'ITEM-DELTAS' ) + * + * ItemDelta ::= 'ITEM(...)' ( ( 'ADD-VALUES(...)' 'DELETE-VALUES(...)'? ) | 'DELETE-VALUES(...)' | 'REPLACE-VALUES(...)' ) + * + * EXPERIMENTAL IMPLEMENTATION. + * + * @author mederly + */ +public class DeltaBuilder implements S_ItemEntry, S_MaybeDelete, S_ValuesEntry { + + final private Class objectClass; + final private ComplexTypeDefinition containerCTD; + final private PrismContext prismContext; + + // BEWARE - although these are final, their content may (and does) vary. Not much clean. + final List deltas; + final ItemDelta currentDelta; + + private DeltaBuilder(Class objectClass, PrismContext prismContext) throws SchemaException { + this.objectClass = objectClass; + this.prismContext = prismContext; + containerCTD = prismContext.getSchemaRegistry().findComplexTypeDefinitionByCompileTimeClass(this.objectClass); + if (containerCTD == null) { + throw new SchemaException("Couldn't find definition for complex type " + this.objectClass); + } + deltas = new ArrayList<>(); + currentDelta = null; + } + + public DeltaBuilder(Class objectClass, ComplexTypeDefinition containerCTD, PrismContext prismContext, List deltas, ItemDelta currentDelta) { + this.objectClass = objectClass; + this.containerCTD = containerCTD; + this.prismContext = prismContext; + this.deltas = deltas; + this.currentDelta = currentDelta; + } + + public Class getObjectClass() { + return objectClass; + } + + public PrismContext getPrismContext() { + return prismContext; + } + + public static S_ItemEntry deltaFor(Class objectClass, PrismContext prismContext) throws SchemaException { + return new DeltaBuilder(objectClass, prismContext); + } + + @Override + public S_ValuesEntry item(QName... names) { + return item(new ItemPath(names)); + } + + @Override + public S_ValuesEntry item(Object... namesOrIds) { + return item(new ItemPath(namesOrIds)); + } + + @Override + public S_ValuesEntry item(ItemPath path) { + ItemDefinition definition = containerCTD.findItemDefinition(path); + if (definition == null) { + throw new IllegalArgumentException("Undefined or dynamic path: " + path + " in: " + containerCTD); + } + return item(path, definition); + } + + @Override + public S_ValuesEntry item(ItemPath path, ItemDefinition definition) { + ItemDelta newDelta; + if (definition instanceof PrismPropertyDefinition) { + newDelta = new PropertyDelta(path, (PrismPropertyDefinition) definition, prismContext); + } else if (definition instanceof PrismContainerDefinition) { + newDelta = new ContainerDelta(path, (PrismContainerDefinition) definition, prismContext); + } else if (definition instanceof PrismReferenceDefinition) { + newDelta = new ReferenceDelta(path, (PrismReferenceDefinition) definition, prismContext); + } else { + throw new IllegalStateException("Unsupported definition type: " + definition); + } + List newDeltas = deltas; + if (currentDelta != null) { + newDeltas.add(currentDelta); + } + return new DeltaBuilder(objectClass, containerCTD, prismContext, newDeltas, newDelta); + } + + @Override + public ObjectDelta asObjectDelta(String oid) { + return ObjectDelta.createModifyDelta(oid, getAllDeltas(), objectClass, prismContext); + } + + @Override + public ItemDelta asItemDelta() { + List allDeltas = getAllDeltas(); + if (allDeltas.size() > 1) { + throw new IllegalStateException("Too many deltas to fit into item delta: " + allDeltas.size()); + } else if (allDeltas.size() == 1) { + return allDeltas.get(0); + } else { + return null; + } + } + + @Override + public List asItemDeltas() { + return getAllDeltas(); + } + + private List getAllDeltas() { + if (currentDelta != null) { + deltas.add(currentDelta); + } + return deltas; + } + + @Override + public S_MaybeDelete add(Object... realValues) { + for (Object v : realValues) { + currentDelta.addValueToAdd(toPrismValue(currentDelta, v)); + } + return this; + } + + @Override + public S_MaybeDelete add(PrismValue... values) { + currentDelta.addValuesToAdd(values); + return this; + } + + @Override + public S_ItemEntry delete(Object... realValues) { + for (Object v : realValues) { + currentDelta.addValueToDelete(toPrismValue(currentDelta, v)); + } + return this; + } + + @Override + public S_ItemEntry delete(PrismValue... values) { + currentDelta.addValuesToDelete(values); + return this; + } + + @Override + public S_ItemEntry replace(Object... realValues) { + List prismValues = new ArrayList<>(); + for (Object v : realValues) { + prismValues.add(toPrismValue(currentDelta, v)); + } + currentDelta.setValuesToReplace(prismValues); + return this; + } + + @Override + public S_ItemEntry replace(PrismValue... values) { + currentDelta.setValuesToReplace(values); + return this; + } + + private PrismValue toPrismValue(ItemDelta currentDelta, Object v) { + ItemDefinition definition = currentDelta.getDefinition(); + if (definition instanceof PrismPropertyDefinition) { + return new PrismPropertyValue<>(v); + } else if (definition instanceof PrismContainerDefinition) { + return ((Containerable) v).asPrismContainerValue(); + } else if (definition instanceof PrismReferenceDefinition) { + throw new IllegalStateException("Using real value for reference deltas is not supported: " + v); + } else { + throw new IllegalStateException("Unsupported definition type: " + definition); + } + } + +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java new file mode 100644 index 00000000000..0ac616af71e --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.delta.builder; + +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemPath; + +import javax.xml.namespace.QName; +import java.util.List; + +/** + * @author mederly + */ +public interface S_ItemEntry { + + S_ValuesEntry item(QName... names); + S_ValuesEntry item(Object... namesOrIds); + S_ValuesEntry item(ItemPath path); + S_ValuesEntry item(ItemPath path, ItemDefinition itemDefinition); + + ObjectDelta asObjectDelta(String oid); + ItemDelta asItemDelta(); + List asItemDeltas(); + +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_MaybeDelete.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_MaybeDelete.java new file mode 100644 index 00000000000..f55e759df36 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_MaybeDelete.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.delta.builder; + +import com.evolveum.midpoint.prism.PrismValue; + +/** + * @author mederly + */ +public interface S_MaybeDelete extends S_ItemEntry { + S_ItemEntry delete(Object... realValues); + S_ItemEntry delete(PrismValue... values); +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java new file mode 100644 index 00000000000..992f2129836 --- /dev/null +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.prism.delta.builder; + +import com.evolveum.midpoint.prism.PrismValue; + +/** + * @author mederly + */ +public interface S_ValuesEntry { + + S_MaybeDelete add(Object... realValues); + S_MaybeDelete add(PrismValue... values); + S_ItemEntry delete(Object... realValues); + S_ItemEntry delete(PrismValue... values); + S_ItemEntry replace(Object... realValues); + S_ItemEntry replace(PrismValue... values); + +} diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index fca5472b763..55df343ded6 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -40,7 +40,7 @@ public class ItemPath implements Serializable, Cloneable { private List segments; private Map namespaceMap; - + public void setNamespaceMap(Map namespaceMap) { this.namespaceMap = namespaceMap; } @@ -67,6 +67,23 @@ public ItemPath(String... names) { } } + public ItemPath(Object[] namesOrIds) { + this.segments = new ArrayList<>(namesOrIds.length); + for (Object nameOrId : namesOrIds) { + if (nameOrId instanceof QName) { + add((QName) nameOrId); + } else if (nameOrId instanceof String) { + add(stringToQName((String) nameOrId)); + } else if (nameOrId instanceof Long) { + this.segments.add(new IdItemPathSegment((Long) nameOrId)); + } else if (nameOrId instanceof Integer) { + this.segments.add(new IdItemPathSegment(((Integer) nameOrId).longValue())); + } else { + throw new IllegalArgumentException("Invalid item path segment value: " + nameOrId); + } + } + } + private QName stringToQName(String name) { Validate.notNull(name, "name"); if ("..".equals(name)) { @@ -124,6 +141,10 @@ public ItemPath(ItemPath parentPath, ItemPathSegment subSegment) { public ItemPath subPath(QName subName) { return new ItemPath(segments, subName); } + + public ItemPath subPath(Long id) { + return subPath(new IdItemPathSegment(id)); + } public ItemPath subPath(ItemPathSegment subSegment) { return new ItemPath(segments, subSegment); @@ -159,7 +180,7 @@ private void add(QName qname) { this.segments.add(new NameItemPathSegment(qname)); } } - + public List getSegments() { return segments; } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java index 84765f36d41..388f582eb14 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java @@ -17,12 +17,22 @@ package com.evolveum.midpoint.repo.sql; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; +import com.evolveum.midpoint.prism.path.IdItemPathSegment; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.util.CloneUtil; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -30,17 +40,39 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; import org.testng.annotations.Test; import java.io.File; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import static com.evolveum.midpoint.prism.delta.PropertyDelta.createModificationReplaceProperty; import static com.evolveum.midpoint.schema.RetrieveOption.INCLUDE; +import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createObjectRef; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REMEDIATION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REVIEW_STAGE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_CASE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_STATE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CAMPAIGN_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CURRENT_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CURRENT_STAGE_NUMBER; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_DECISION; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_REVIEWER_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_COMMENT; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.ACCEPT; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.DELEGATE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NOT_DECIDED; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_NAME; /** * @author lazyman @@ -51,12 +83,16 @@ public class CertificationTest extends BaseSQLRepoTest { private static final Trace LOGGER = TraceManager.getTrace(CertificationTest.class); private static final File TEST_DIR = new File("src/test/resources/cert"); + public static final File CAMPAIGN_1_FILE = new File(TEST_DIR, "cert-campaign-1.xml"); private String campaignOid; + private PrismObjectDefinition campaignDef; @Test public void test100AddCampaignNonOverwrite() throws Exception { - PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + PrismObject campaign = prismContext.parseObject(CAMPAIGN_1_FILE); + campaignDef = campaign.getDefinition(); + OperationResult result = new OperationResult("test100AddCampaignNonOverwrite"); campaignOid = repositoryService.addObject(campaign, null, result); @@ -64,44 +100,182 @@ public void test100AddCampaignNonOverwrite() throws Exception { result.recomputeStatus(); AssertJUnit.assertTrue(result.isSuccess()); - // rereading, as repo strips cases from the campaign (!) - PrismObject expected = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); - checkCampaign(campaignOid, expected, result); - } - - private void checkCampaign(String campaignOid, PrismObject expectedObject, OperationResult result) throws SchemaException, ObjectNotFoundException { - SelectorOptions retrieve = SelectorOptions.create(F_CASE, GetOperationOptions.createRetrieve(INCLUDE)); - PrismObject campaign = repositoryService.getObject(AccessCertificationCampaignType.class, campaignOid, Arrays.asList(retrieve), result); - expectedObject.setOid(campaignOid); - removeCampaignRef(campaign.asObjectable()); - PrismAsserts.assertEquivalent("Campaign is not as expected", expectedObject, campaign); - } - - private void removeCampaignRef(AccessCertificationCampaignType campaign) { - for (AccessCertificationCaseType aCase : campaign.getCase()) { - aCase.asPrismContainerValue().removeReference(F_CAMPAIGN_REF); - } + checkCampaign(campaignOid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); } @Test(expectedExceptions = ObjectAlreadyExistsException.class) public void test105AddCampaignNonOverwriteExisting() throws Exception { - PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + PrismObject campaign = prismContext.parseObject(CAMPAIGN_1_FILE); OperationResult result = new OperationResult("test105AddCampaignNonOverwriteExisting"); repositoryService.addObject(campaign, null, result); } @Test public void test108AddCampaignOverwriteExisting() throws Exception { - PrismObject campaign = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); + PrismObject campaign = prismContext.parseObject(CAMPAIGN_1_FILE); OperationResult result = new OperationResult("test108AddCampaignOverwriteExisting"); campaign.setOid(campaignOid); // doesn't work without specifying OID campaignOid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); - // rereading, as repo strips cases from the campaign (!) - PrismObject expected = prismContext.parseObject(new File(TEST_DIR, "cert-campaign-1.xml")); - checkCampaign(campaignOid, expected, result); + checkCampaign(campaignOid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + } + + @Test + public void test200ModifyCampaignProperties() throws Exception { + OperationResult result = new OperationResult("test200ModifyCampaignProperties"); + + List modifications = new ArrayList<>(); + modifications.add(createModificationReplaceProperty(F_NAME, campaignDef, new PolyString("Campaign 1+", "campaign 1"))); + modifications.add(createModificationReplaceProperty(F_STATE, campaignDef, IN_REVIEW_STAGE)); + + executeAndCheckModification(modifications, result); } + @Test + public void test210ModifyCaseProperties() throws Exception { + OperationResult result = new OperationResult("test210ModifyCaseProperties"); + + List modifications = new ArrayList<>(); + ItemPath case1 = new ItemPath(F_CASE).subPath(new IdItemPathSegment(1L)); + modifications.add(createModificationReplaceProperty(case1.subPath(F_CURRENT_RESPONSE), campaignDef, DELEGATE)); + modifications.add(createModificationReplaceProperty(case1.subPath(F_CURRENT_STAGE_NUMBER), campaignDef, 300)); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test220ModifyDecisionProperties() throws Exception { + OperationResult result = new OperationResult("test220ModifyDecisionProperties"); + + List modifications = new ArrayList<>(); + ItemPath d1 = new ItemPath(F_CASE).subPath(1L).subPath(F_DECISION).subPath(1L); + modifications.add(createModificationReplaceProperty(d1.subPath(F_RESPONSE), campaignDef, DELEGATE)); + modifications.add(createModificationReplaceProperty(d1.subPath(F_COMMENT), campaignDef, "hi")); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test230ModifyAllLevels() throws Exception { + OperationResult result = new OperationResult("test230ModifyAllLevels"); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_NAME).replace(new PolyString("Campaign 2", "campaign 2")) + .item(F_STATE).replace(IN_REMEDIATION) + .item(F_CASE, 2, F_CURRENT_RESPONSE).replace(NO_RESPONSE) + .item(F_CASE, 2, F_CURRENT_STAGE_NUMBER).replace(400) + .item(F_CASE, 1, F_DECISION, 1, F_RESPONSE).replace(NOT_DECIDED) + .item(F_CASE, 1, F_DECISION, 1, F_COMMENT).replace("low") + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test240AddCases() throws Exception { + OperationResult result = new OperationResult("test240AddDeleteCases"); + + AccessCertificationCaseType caseNoId = new AccessCertificationCaseType(prismContext); + caseNoId.setObjectRef(createObjectRef("123", ObjectTypes.USER)); + caseNoId.setTargetRef(createObjectRef("456", ObjectTypes.ROLE)); + caseNoId.setCurrentStageNumber(1); + + AccessCertificationCaseType case100 = new AccessCertificationCaseType(prismContext); + case100.setId(100L); + case100.setObjectRef(createObjectRef("100123", ObjectTypes.USER)); + case100.setTargetRef(createObjectRef("100456", ObjectTypes.ROLE)); + case100.getReviewerRef().add(createObjectRef("100789", ObjectTypes.USER)); + case100.setCurrentStageNumber(1); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE).add(caseNoId, case100) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test242DeleteCase() throws Exception { + OperationResult result = new OperationResult("test242DeleteCase"); + + AccessCertificationCaseType case7 = new AccessCertificationCaseType(); + case7.setId(7L); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE).delete(case7) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test244ModifyCase() throws Exception { + OperationResult result = new OperationResult("test244ModifyCase"); + + AccessCertificationCaseType case7 = new AccessCertificationCaseType(); + case7.setId(7L); + + PrismReferenceValue reviewerToDelete = createObjectRef("100789", ObjectTypes.USER).asReferenceValue(); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE, 100, F_REVIEWER_REF).delete(reviewerToDelete) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + + @Test + public void test248AddDeleteModifyCase() throws Exception { + OperationResult result = new OperationResult("test248AddDeleteModifyCase"); + + AccessCertificationCaseType caseNoId = new AccessCertificationCaseType(prismContext); + caseNoId.setObjectRef(createObjectRef("x123", ObjectTypes.USER)); + caseNoId.setTargetRef(createObjectRef("x456", ObjectTypes.ROLE)); + caseNoId.setCurrentStageNumber(1); + + AccessCertificationCaseType case110 = new AccessCertificationCaseType(prismContext); + case110.setId(110L); + case110.setObjectRef(createObjectRef("x100123", ObjectTypes.USER)); + case110.setTargetRef(createObjectRef("x100456", ObjectTypes.ROLE)); + case110.getReviewerRef().add(createObjectRef("x100789", ObjectTypes.USER)); + case110.setCurrentStageNumber(1); + + AccessCertificationCaseType case100 = new AccessCertificationCaseType(); + case100.setId(100L); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE).add(caseNoId, case110).delete(case100) + .item(F_CASE, 3, F_CURRENT_STAGE_NUMBER).replace(400) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test250AddDeleteModifyResponse() throws Exception { + OperationResult result = new OperationResult("test250AddDeleteModifyResponse"); + + AccessCertificationDecisionType decNoId = new AccessCertificationDecisionType(prismContext); + decNoId.setReviewerRef(createObjectRef("888", ObjectTypes.USER)); + decNoId.setStageNumber(1); + + AccessCertificationDecisionType dec200 = new AccessCertificationDecisionType(prismContext); + dec200.setId(200L); + dec200.setStageNumber(1); + dec200.setReviewerRef(createObjectRef("200888", ObjectTypes.USER)); + + AccessCertificationDecisionType dec1 = new AccessCertificationDecisionType(); + dec1.setId(1L); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE, 6, F_DECISION).add(decNoId, dec200) + .item(F_CASE, 6, F_DECISION).delete(dec1) + .item(F_CASE, 6, F_DECISION, 2, F_RESPONSE).replace(ACCEPT) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } @Test @@ -111,4 +285,42 @@ public void test900DeleteCampaign() throws Exception { result.recomputeStatus(); AssertJUnit.assertTrue(result.isSuccess()); } + + protected void executeAndCheckModification(List modifications, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, IOException { + PrismObject before = getFullCampaign(campaignOid, result); + List savedModifications = (List) CloneUtil.cloneCollectionMembers(modifications); + + repositoryService.modifyObject(AccessCertificationCampaignType.class, campaignOid, modifications, result); + + checkCampaign(campaignOid, result, before, savedModifications); + } + + private void checkCampaign(String campaignOid, OperationResult result, PrismObject expectedObject, List modifications) throws SchemaException, ObjectNotFoundException, IOException { + expectedObject.setOid(campaignOid); + if (modifications != null) { + ItemDelta.applyTo(modifications, expectedObject); + } + + LOGGER.trace("Expected object = \n{}", expectedObject.debugDump()); + + PrismObject campaign = getFullCampaign(campaignOid, result); + + LOGGER.trace("Actual object from repo = \n{}", campaign.debugDump()); + + removeCampaignRef(expectedObject.asObjectable()); + removeCampaignRef(campaign.asObjectable()); + PrismAsserts.assertEquivalent("Campaign is not as expected", expectedObject, campaign); + } + + private PrismObject getFullCampaign(String campaignOid, OperationResult result) throws ObjectNotFoundException, SchemaException { + SelectorOptions retrieve = SelectorOptions.create(F_CASE, GetOperationOptions.createRetrieve(INCLUDE)); + return repositoryService.getObject(AccessCertificationCampaignType.class, campaignOid, Arrays.asList(retrieve), result); + } + + private void removeCampaignRef(AccessCertificationCampaignType campaign) { + for (AccessCertificationCaseType aCase : campaign.getCase()) { + aCase.asPrismContainerValue().removeReference(F_CAMPAIGN_REF); + } + } + } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java new file mode 100644 index 00000000000..4868758865f --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.repo.sql; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.repo.api.RepoAddOptions; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.io.File; +import java.util.Arrays; + +import static com.evolveum.midpoint.schema.RetrieveOption.INCLUDE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_CAMPAIGN_REF; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType.F_ROW; + +/** + * @author lazyman + */ +@ContextConfiguration(locations = {"../../../../../ctx-test.xml"}) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +public class LookupTableTest extends BaseSQLRepoTest { + + private static final Trace LOGGER = TraceManager.getTrace(LookupTableTest.class); + private static final File TEST_DIR = new File("src/test/resources/lookup"); + + private String tableOid; + + @Test + public void test100AddTableNonOverwrite() throws Exception { + PrismObject table = prismContext.parseObject(new File(TEST_DIR, "table-1.xml")); + OperationResult result = new OperationResult("test100AddTableNonOverwrite"); + + tableOid = repositoryService.addObject(table, null, result); + + result.recomputeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + + // rereading + PrismObject expected = prismContext.parseObject(new File(TEST_DIR, "table-1.xml")); + checkTable(tableOid, expected, result); + } + + private void checkTable(String tableOid, PrismObject expectedObject, OperationResult result) throws SchemaException, ObjectNotFoundException { + SelectorOptions retrieve = SelectorOptions.create(F_ROW, GetOperationOptions.createRetrieve(INCLUDE)); + PrismObject table = repositoryService.getObject(LookupTableType.class, tableOid, Arrays.asList(retrieve), result); + expectedObject.setOid(tableOid); + PrismAsserts.assertEquivalent("Table is not as expected", expectedObject, table); + } + + @Test(expectedExceptions = ObjectAlreadyExistsException.class) + public void test105AddTableNonOverwriteExisting() throws Exception { + PrismObject table = prismContext.parseObject(new File(TEST_DIR, "table-1.xml")); + OperationResult result = new OperationResult("test105AddTableNonOverwriteExisting"); + repositoryService.addObject(table, null, result); + } + + @Test + public void test108AddTableOverwriteExisting() throws Exception { + PrismObject table = prismContext.parseObject(new File(TEST_DIR, "table-1.xml")); + OperationResult result = new OperationResult("test108AddTableOverwriteExisting"); + table.setOid(tableOid); // doesn't work without specifying OID + tableOid = repositoryService.addObject(table, RepoAddOptions.createOverwrite(), result); + + // rereading, as repo strips cases from the campaign (!) + PrismObject expected = prismContext.parseObject(new File(TEST_DIR, "table-1.xml")); + checkTable(tableOid, expected, result); + } + + @Test + public void test900DeleteTable() throws Exception { + OperationResult result = new OperationResult("test900DeleteTable"); + repositoryService.deleteObject(LookupTableType.class, tableOid, result); + result.recomputeStatus(); + AssertJUnit.assertTrue(result.isSuccess()); + } +} diff --git a/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml b/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml index 0428c201a16..25356834e2d 100644 --- a/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml +++ b/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-1.xml @@ -220,6 +220,11 @@ reduce 2015-12-04T01:10:15.375+01:00 + + 2 + + reduce 1 @@ -228,9 +233,9 @@ false + xsi:type="c:AccessCertificationAssignmentCaseType"> + 2015-12-04T00:38:00.708+01:00 @@ -242,6 +247,13 @@ revoke 2015-12-04T01:10:16.136+01:00 + + 1 + + accept + 2015-12-04T01:15:00.000+01:00 + revoke 1 diff --git a/repo/repo-sql-impl-test/src/test/resources/logback-test.xml b/repo/repo-sql-impl-test/src/test/resources/logback-test.xml index 091533d3971..68d7da81f2e 100644 --- a/repo/repo-sql-impl-test/src/test/resources/logback-test.xml +++ b/repo/repo-sql-impl-test/src/test/resources/logback-test.xml @@ -33,6 +33,9 @@ + + + diff --git a/repo/repo-sql-impl-test/src/test/resources/lookup/table-1.xml b/repo/repo-sql-impl-test/src/test/resources/lookup/table-1.xml new file mode 100644 index 00000000000..4599c8c04f7 --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/resources/lookup/table-1.xml @@ -0,0 +1,47 @@ + + + + + first lookup + description of lookuptable + + first key + first value + + 2013-05-07T10:38:21.350+02:00 + + + 2 key + 2 value + + 2013-05-07T10:38:21.350+02:00 + + + 3 key + 3 value + + 2013-05-07T10:38:21.350+02:00 + + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java index d7d6b0f7e58..afd9e82633f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationCampaign.java @@ -192,7 +192,7 @@ public static void copyFromJAXB(AccessCertificationCampaignType jaxb, RAccessCer for (AccessCertificationCaseType case1 : cases) { case1.setCampaignRef(ObjectTypeUtil.createObjectRef(jaxb)); RAccessCertificationCase rCase = RAccessCertificationCase.toRepo(repo, case1, generatorResult, prismContext); - rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); + rCase.setTransient(generatorResult.isTransient(case1.asPrismContainerValue())); // redundant? repo.getCase().add(rCase); } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java index dfc487b19bd..5588da3fad7 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RObject.java @@ -114,7 +114,8 @@ @NamedQuery(name = "delete.campaignCasesReferences", query = "delete RCertCaseReference r where r.ownerOid = :oid"), @NamedQuery(name = "delete.campaignCase", query = "delete RAccessCertificationCase c where c.ownerOid = :oid and c.id = :id"), @NamedQuery(name = "delete.campaignCaseDecisions", query = "delete RAccessCertificationDecision d where d.ownerOwnerOid = :oid and d.ownerId = :id"), - @NamedQuery(name = "delete.campaignCaseReferences", query = "delete RCertCaseReference r where r.ownerOid = :oid and r.id = :id"), + // doesn't work; generates SQL of "delete from m_acc_cert_case_reference where owner_owner_oid=? and owner_id=? and owner_owner_oid=? and reference_type=? and relation=? and targetOid=?" + //@NamedQuery(name = "delete.campaignCaseReferences", query = "delete RCertCaseReference r where r.ownerOid = :oid and r.id = :id"), @NamedQuery(name = "resolveReferences", query = "select o.oid, o.name from RObject as o where o.oid in (:oid)"), @NamedQuery(name = "get.campaignCase", query = "select c.fullObject from RAccessCertificationCase c where c.ownerOid=:ownerOid and c.id=:id") }) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java index a817fda339a..498e4d4e375 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java @@ -55,11 +55,13 @@ @JaxbType(type = ObjectReferenceType.class) @Entity @IdClass(RCObjectReferenceId.class) -@Table(name = "m_acc_cert_case_reference", indexes = { +@Table(name = RCertCaseReference.TABLE, indexes = { @javax.persistence.Index(name = "iAccCertCaseReferenceTargetOid", columnList = "targetOid") }) public class RCertCaseReference extends RContainerReference { + public static final String TABLE = "m_acc_cert_case_reference"; + private RAccessCertificationCase owner; // private RPolyString targetName; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 502a1fdc12f..a3b255cbfd6 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -26,6 +26,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; +import com.evolveum.midpoint.repo.sql.data.common.container.RCertCaseReference; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.PrismIdentifierGenerator; @@ -83,6 +84,7 @@ public void addCertificationCampaignCases(Session session, RObject object, boole RAccessCertificationCampaign campaign = (RAccessCertificationCampaign) object; if (merge) { + LOGGER.info("Deleting existing cases for {}", campaign.getOid()); deleteCertificationCampaignCases(session, campaign.getOid()); } if (campaign.getCase() != null) { @@ -92,14 +94,18 @@ public void addCertificationCampaignCases(Session session, RObject object, boole } } - public void addCertificationCampaignCases(Session session, String campaignOid, Collection values, int currentId) { + public void addCertificationCampaignCases(Session session, String campaignOid, Collection values, int currentId, List affectedIds) { for (PrismContainerValue value : values) { AccessCertificationCaseType caseType = new AccessCertificationCaseType(); caseType.setupContainerValue(value); caseType.setCampaignRef(ObjectTypeUtil.createObjectRef(campaignOid, ObjectTypes.ACCESS_CERTIFICATION_CAMPAIGN)); + if (caseType.getId() == null) { + caseType.setId((long) currentId); + currentId++; + } RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, null, prismContext); - row.setId(currentId); - currentId++; + row.setId(RUtil.toInteger(caseType.getId())); + affectedIds.add(caseType.getId()); session.save(row); } } @@ -188,7 +194,8 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle deleteCaseDecisions.setString("oid", campaignOid); deleteCaseDecisions.setInteger("id", integerCaseId); deleteCaseDecisions.executeUpdate(); - Query deleteCaseReferences = session.getNamedQuery("delete.campaignCaseReferences"); + Query deleteCaseReferences = session.createSQLQuery("delete from " + RCertCaseReference.TABLE + + " where owner_owner_oid=:oid and owner_id=:id"); deleteCaseReferences.setString("oid", campaignOid); deleteCaseReferences.setInteger("id", integerCaseId); deleteCaseReferences.executeUpdate(); @@ -200,12 +207,11 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle } if (delta.getValuesToAdd() != null) { int currentId = generalHelper.findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; - affectedIds.add((long) currentId); // TODO !!!!!!!!!!!!!!!!!! clear bug - addCertificationCampaignCases(session, campaignOid, delta.getValuesToAdd(), currentId); + addCertificationCampaignCases(session, campaignOid, delta.getValuesToAdd(), currentId, affectedIds); } if (delta.getValuesToReplace() != null) { deleteCertificationCampaignCases(session, campaignOid); - addCertificationCampaignCases(session, campaignOid, delta.getValuesToReplace(), 1); + addCertificationCampaignCases(session, campaignOid, delta.getValuesToReplace(), 1, affectedIds); replacePresent = true; } @@ -233,6 +239,7 @@ private void updateCasesContent(Session session, String campaignOid, Collection< } AccessCertificationCaseType aCase = RAccessCertificationCase.createJaxb(fullObject, prismContext, false); + delta = delta.clone(); // to avoid changing original modifications delta.setParentPath(delta.getParentPath().tail(2)); // remove "case[id]" from the delta path delta.applyTo(aCase.asPrismContainerValue()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java index 74ae89095fe..ddaeadb77a1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java @@ -89,7 +89,7 @@ @Component public class ObjectRetriever { - private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); + private static final Trace LOGGER = TraceManager.getTrace(ObjectRetriever.class); private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(SqlRepositoryServiceImpl.PERFORMANCE_LOG_NAME); @Autowired diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java index 8f5d780a584..8582075ec37 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -76,7 +76,7 @@ @Component public class ObjectUpdater { - private static final Trace LOGGER = TraceManager.getTrace(SqlRepositoryServiceImpl.class); + private static final Trace LOGGER = TraceManager.getTrace(ObjectUpdater.class); private static final Trace LOGGER_PERFORMANCE = TraceManager.getTrace(SqlRepositoryServiceImpl.PERFORMANCE_LOG_NAME); @Autowired @@ -345,10 +345,9 @@ public void modifyObjectAttempt(Class type, String oid modifications = new ArrayList<>(modifications); LOGGER.debug("Modifying object '{}' with oid '{}'.", new Object[]{type.getSimpleName(), oid}); - LOGGER_PERFORMANCE.debug("> modify object {}, oid={}, modifications={}", - new Object[]{type.getSimpleName(), oid, modifications}); + LOGGER_PERFORMANCE.debug("> modify object {}, oid={}, modifications={}", type.getSimpleName(), oid, modifications); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Modifications:\n{}", new Object[]{DebugUtil.debugDump(modifications)}); + LOGGER.trace("Modifications:\n{}", DebugUtil.debugDump(modifications)); } Session session = null; @@ -409,6 +408,7 @@ public void modifyObjectAttempt(Class type, String oid rObject.setVersion(rObject.getVersion() + 1); updateFullObject(rObject, prismObject); + LOGGER.trace("Starting merge."); session.merge(rObject); lookupTableHelper.updateLookupTableData(session, rObject, lookupTableModifications); From cc78beac8e1057d696944696a5a9e67fb1855f60 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Wed, 9 Dec 2015 12:49:33 +0100 Subject: [PATCH 081/116] AssignmentEvaluator extension to process adminGuiConfig, storing in principal, some user dashboard improvements --- .../web/page/self/PageSelfDashboard.java | 23 +++++- .../web/page/self/component/LinksPanel.java | 34 ++++++++- .../midpoint/web/util/WebMiscUtil.java | 4 +- .../schema/util/AdminGuiConfigTypeUtil.java | 73 +++++++++++++++++++ .../api/context/EvaluatedAssignment.java | 3 + .../ModelInteractionServiceImpl.java | 20 ++++- .../model/impl/lens/AssignmentEvaluator.java | 3 + .../impl/lens/EvaluatedAssignmentImpl.java | 11 +++ .../impl/security/UserProfileServiceImpl.java | 45 +++++++++--- .../impl/lens/TestAssignmentEvaluator.java | 16 +++- .../resources/lens/role-corp-engineer.xml | 18 +++++ .../model/intest/TestPreviewChanges.java | 3 +- .../midpoint/model/intest/TestSecurity.java | 4 + .../src/test/resources/common/role-pirate.xml | 20 ++++- .../resources/common/system-configuration.xml | 8 ++ .../test/AbstractModelIntegrationTest.java | 19 +++++ .../security/api/MidPointPrincipal.java | 13 +++- .../security/api/UserProfileService.java | 4 +- 18 files changed, 291 insertions(+), 30 deletions(-) create mode 100644 infra/schema/src/main/java/com/evolveum/midpoint/schema/util/AdminGuiConfigTypeUtil.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java index cb66ce88dde..f369ac09e5d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageSelfDashboard.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.evolveum.midpoint.web.page.self; import com.evolveum.midpoint.prism.PrismObject; @@ -41,6 +56,7 @@ /** * @author Viliam Repan (lazyman) + * @author Kate Honchar */ @PageDescriptor(url = {"/self/dashboard", "/self"}, action = { @AuthorizationAction(actionUri = PageSelf.AUTH_SELF_ALL_URI, @@ -263,7 +279,7 @@ private PrismObject loadUser() { return user; } - private List loadLinksList(){ + private List loadLinksList() { List list = new ArrayList(); PrismObject user = principalModel.getObject(); @@ -274,8 +290,9 @@ private List loadLinksList(){ OperationResult result = new OperationResult(OPERATION_LOAD_WORK_ITEMS); Task task = createSimpleTask(TASK_GET_SYSTEM_CONFIG); - try{ + try { AdminGuiConfigurationType adminGuiConfig = getModelInteractionService().getAdminGuiConfiguration(task, result); +// LOGGER.trace("Admin GUI config: {}", adminGuiConfig); list = adminGuiConfig.getUserDashboardLink(); result.recordSuccess(); } catch(Exception ex){ @@ -285,7 +302,7 @@ private List loadLinksList(){ return list; } - private void createLinksPanelModel(){ + private void createLinksPanelModel() { linksPanelModel = new IModel>() { @Override public List getObject() { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java index f7324496303..1d7af85c7a0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java @@ -1,8 +1,26 @@ +/* + * Copyright (c) 2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.evolveum.midpoint.web.page.self.component; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.util.SimplePanel; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; @@ -13,10 +31,11 @@ import org.apache.wicket.protocol.http.WebApplication; import javax.servlet.ServletContext; + import java.util.List; /** - * Created by Kate on 23.09.2015. + * @author Kate Honchar */ public class LinksPanel extends SimplePanel> { private static final String DOT_CLASS = LinksPanel.class.getName() + "."; @@ -26,7 +45,10 @@ public class LinksPanel extends SimplePanel> { private static final String ID_DESCRIPTION = "descriptionId"; private static final String ID_LINKS_ROW = "linksRow"; private static final String ID_LINKS_COLUMN = "linksColumn"; - private static final String OPERATION_LOAD_LINKS = DOT_CLASS + "loadLinks"; + + private static final String ICON_DEFAULT_CSS_CLASS = "fa fa-angle-double-right"; + + private static final Trace LOGGER = TraceManager.getTrace(LinksPanel.class); IModel> model; @@ -85,9 +107,13 @@ protected void onComponentTag(final ComponentTag tag) { @Override protected void onComponentTag(final ComponentTag tag) { super.onComponentTag(tag); + String cssClass = ICON_DEFAULT_CSS_CLASS; + if (link.getIcon() != null) { + cssClass = link.getIcon().getCssClass(); + } tag.put("class", "info-box-icon " + (link.getColor() != null ? (link.getColor().startsWith("bg-") ? link.getColor() : "bg-" + link.getColor()) : "") + " " - + link.getIcon().getCssClass()); + + cssClass); } }); @@ -113,6 +139,8 @@ public String getObject() { } else { currentColumn++; } + } else { + LOGGER.trace("Link {} not authorized, skipping", link); } } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java index d4af436056f..585dcc1e5da 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/WebMiscUtil.java @@ -137,7 +137,7 @@ private WebMiscUtil() { } public static boolean isAuthorized(String... action) { - if (action == null) { + if (action == null || action.length == 0) { return true; } List actions = Arrays.asList(action); @@ -145,7 +145,7 @@ public static boolean isAuthorized(String... action) { } public static boolean isAuthorized(Collection actions) { - if (actions == null) { + if (actions == null || actions.isEmpty()) { return true; } Roles roles = new Roles(AuthorizationConstants.AUTZ_ALL_URL); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/AdminGuiConfigTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/AdminGuiConfigTypeUtil.java new file mode 100644 index 00000000000..9eb396ef580 --- /dev/null +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/AdminGuiConfigTypeUtil.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.schema.util; + +import java.util.Collection; +import java.util.Iterator; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AdminGuiConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectFormType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectFormsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; + +/** + * @author semancik + * + */ +public class AdminGuiConfigTypeUtil { + + public static AdminGuiConfigurationType compileAdminGuiConfiguration(Collection adminGuiConfigurations, + PrismObject systemConfiguration) { + AdminGuiConfigurationType composite = new AdminGuiConfigurationType(); + if (systemConfiguration != null) { + applyAdminGuiConfiguration(composite, systemConfiguration.asObjectable().getAdminGuiConfiguration()); + } + for (AdminGuiConfigurationType adminGuiConfiguration: adminGuiConfigurations) { + applyAdminGuiConfiguration(composite, adminGuiConfiguration); + } + return composite; + } + + private static void applyAdminGuiConfiguration(AdminGuiConfigurationType composite, AdminGuiConfigurationType adminGuiConfiguration) { + if (adminGuiConfiguration == null) { + return; + } + composite.getAdditionalMenuLink().addAll(adminGuiConfiguration.getAdditionalMenuLink()); + composite.getUserDashboardLink().addAll(adminGuiConfiguration.getUserDashboardLink()); + if (adminGuiConfiguration.getObjectForms() != null) { + if (composite.getObjectForms() == null) { + composite.setObjectForms(adminGuiConfiguration.getObjectForms().clone()); + } else { + for (ObjectFormType objectForm: adminGuiConfiguration.getObjectForms().getObjectForm()) { + replaceForm(composite.getObjectForms(), objectForm.clone()); + } + } + } + } + + private static void replaceForm(ObjectFormsType objectForms, ObjectFormType newForm) { + Iterator iterator = objectForms.getObjectForm().iterator(); + while (iterator.hasNext()) { + ObjectFormType currentForm = iterator.next(); + if (currentForm.getType().equals(newForm.getType())) { + iterator.remove(); + } + } + objectForms.getObjectForm().add(newForm); + } + +} diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java index 943e7d8d070..a9d2e648d23 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/EvaluatedAssignment.java @@ -10,6 +10,7 @@ import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AdminGuiConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; @@ -19,6 +20,8 @@ public interface EvaluatedAssignment extends DebugDumpable Collection getAuthorizations(); + Collection getAdminGuiConfigurations(); + DeltaSetTriple getRoles(); DeltaSetTriple getEvaluatedConstructions(Task task, OperationResult result) throws SchemaException, ObjectNotFoundException; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java index 5263eea4e00..4896888834d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java @@ -66,6 +66,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.midpoint.security.api.ObjectSecurityConstraints; import com.evolveum.midpoint.security.api.SecurityEnforcer; import com.evolveum.midpoint.task.api.Task; @@ -593,11 +594,22 @@ public CredentialsPolicyType getCredentialsPolicy(PrismObject user, Ta @Override public AdminGuiConfigurationType getAdminGuiConfiguration(Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { - PrismObject systemConfiguration = objectResolver.getSystemConfiguration(parentResult); - if (systemConfiguration == null) { - return null; + MidPointPrincipal principal = null; + try { + principal = securityEnforcer.getPrincipal(); + } catch (SecurityViolationException e) { + LOGGER.warn("Security violation while getting principlal to get GUI config: {}", e.getMessage(), e); + } + + if (principal == null) { + PrismObject systemConfiguration = objectResolver.getSystemConfiguration(parentResult); + if (systemConfiguration == null) { + return null; + } + return systemConfiguration.asObjectable().getAdminGuiConfiguration(); + } else { + return principal.getAdminGuiConfiguration(); } - return systemConfiguration.asObjectable().getAdminGuiConfiguration(); } @Override diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java index e570dc866a3..d097eead23b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java @@ -543,6 +543,9 @@ private boolean evaluateAbstractRole(EvaluatedAssignmentImpl assignment, Assi Authorization authorization = createAuthorization(authorizationType, roleType.toString()); assignment.addAuthorization(authorization); } + if (roleType.getAdminGuiConfiguration() != null) { + assignment.addAdminGuiConfiguration(roleType.getAdminGuiConfiguration()); + } } return mode != PlusMinusZero.MINUS; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java index 3823fa3eeb3..85f349eb691 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/EvaluatedAssignmentImpl.java @@ -41,6 +41,7 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AdminGuiConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; @@ -63,6 +64,7 @@ public class EvaluatedAssignmentImpl implements EvaluatedAs private Collection membershipRefVals; private Collection authorizations; private Collection,? extends PrismPropertyDefinition>> focusMappings; + private Collection adminGuiConfigurations; private PrismObject target; private boolean isValid; private boolean forceRecon; // used also to force recomputation of parentOrgRefs @@ -76,6 +78,7 @@ public EvaluatedAssignmentImpl() { membershipRefVals = new ArrayList<>(); authorizations = new ArrayList<>(); focusMappings = new ArrayList<>(); + adminGuiConfigurations = new ArrayList<>(); } public ItemDeltaItem,PrismContainerDefinition> getAssignmentIdi() { @@ -177,6 +180,14 @@ public void addAuthorization(Authorization authorization) { authorizations.add(authorization); } + public Collection getAdminGuiConfigurations() { + return adminGuiConfigurations; + } + + public void addAdminGuiConfiguration(AdminGuiConfigurationType adminGuiConfiguration) { + adminGuiConfigurations.add(adminGuiConfiguration); + } + public Collection,? extends PrismPropertyDefinition>> getFocusMappings() { return focusMappings; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java index 571bcf0f709..02d22e96e62 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java @@ -39,6 +39,7 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.AdminGuiConfigTypeUtil; import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.schema.util.ObjectResolver; import com.evolveum.midpoint.security.api.Authorization; @@ -64,6 +65,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -105,9 +107,10 @@ public class UserProfileServiceImpl implements UserProfileService, UserDetailsSe @Override public MidPointPrincipal getPrincipal(String username) throws ObjectNotFoundException { + OperationResult result = new OperationResult(OPERATION_GET_PRINCIPAL); PrismObject user = null; try { - user = findByUsername(username); + user = findByUsername(username, result); } catch (ObjectNotFoundException ex) { LOGGER.trace("Couldn't find user with name '{}', reason: {}.", new Object[]{username, ex.getMessage(), ex}); @@ -118,38 +121,52 @@ public MidPointPrincipal getPrincipal(String username) throws ObjectNotFoundExce throw new SystemException(ex.getMessage(), ex); } - return getPrincipal(user); + return createPrincipal(user, result); } @Override public MidPointPrincipal getPrincipal(PrismObject user) { + OperationResult result = new OperationResult(OPERATION_GET_PRINCIPAL); + return createPrincipal(user, result); + } + + private MidPointPrincipal createPrincipal(PrismObject user, OperationResult result) { if (user == null) { return null; } + + PrismObject systemConfiguration = null; + try { + systemConfiguration = repositoryService.getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), + null, result); + } catch (ObjectNotFoundException | SchemaException e) { + LOGGER.warn("No system configuration: {}", e.getMessage(), e); + } userComputer.recompute(user); MidPointPrincipal principal = new MidPointPrincipal(user.asObjectable()); - addAuthorizations(principal); + initializePrincipalFromAssignments(principal, systemConfiguration); return principal; } @Override public void updateUser(MidPointPrincipal principal) { + OperationResult result = new OperationResult(OPERATION_UPDATE_USER); try { - save(principal); + save(principal, result); } catch (RepositoryException ex) { LOGGER.warn("Couldn't save user '{}, ({})', reason: {}.", new Object[]{principal.getFullName(), principal.getOid(), ex.getMessage()}); } } - private PrismObject findByUsername(String username) throws SchemaException, ObjectNotFoundException { + private PrismObject findByUsername(String username, OperationResult result) throws SchemaException, ObjectNotFoundException { PolyString usernamePoly = new PolyString(username); ObjectQuery query = ObjectQueryUtil.createNormNameQuery(usernamePoly, prismContext); LOGGER.trace("Looking for user, query:\n" + query.debugDump()); List> list = repositoryService.searchObjects(UserType.class, query, null, - new OperationResult("Find by username")); + result); LOGGER.trace("Users found: {}.", (list != null ? list.size() : 0)); if (list == null || list.size() != 1) { return null; @@ -158,13 +175,17 @@ private PrismObject findByUsername(String username) throws SchemaExcep return list.get(0); } - private void addAuthorizations(MidPointPrincipal principal) { + private void initializePrincipalFromAssignments(MidPointPrincipal principal, PrismObject systemConfiguration) { UserType userType = principal.getUser(); Collection authorizations = principal.getAuthorities(); + Collection adminGuiConfigurations = new ArrayList<>(); CredentialsType credentials = userType.getCredentials(); if (userType.getAssignment().isEmpty()) { + if (systemConfiguration != null) { + principal.setAdminGuiConfiguration(systemConfiguration.asObjectable().getAdminGuiConfiguration()); + } return; } @@ -199,6 +220,7 @@ private void addAuthorizations(MidPointPrincipal principal) { EvaluatedAssignment assignment = assignmentEvaluator.evaluate(assignmentIdi, false, userType, userType.toString(), task, result); if (assignment.isValid()) { authorizations.addAll(assignment.getAuthorizations()); + adminGuiConfigurations.addAll(assignment.getAdminGuiConfigurations()); } } catch (SchemaException e) { LOGGER.error("Schema violation while processing assignment of {}: {}; assignment: {}", @@ -214,11 +236,12 @@ private void addAuthorizations(MidPointPrincipal principal) { new Object[]{userType, e.getMessage(), assignmentType, e}); } } + principal.setAdminGuiConfiguration(AdminGuiConfigTypeUtil.compileAdminGuiConfiguration(adminGuiConfigurations, systemConfiguration)); } - private MidPointPrincipal save(MidPointPrincipal person) throws RepositoryException { + private MidPointPrincipal save(MidPointPrincipal person, OperationResult result) throws RepositoryException { try { - UserType oldUserType = getUserByOid(person.getOid()); + UserType oldUserType = getUserByOid(person.getOid(), result); PrismObject oldUser = oldUserType.asPrismObject(); PrismObject newUser = person.getUser().asPrismObject(); @@ -233,9 +256,9 @@ private MidPointPrincipal save(MidPointPrincipal person) throws RepositoryExcept return person; } - private UserType getUserByOid(String oid) throws ObjectNotFoundException, SchemaException { + private UserType getUserByOid(String oid, OperationResult result) throws ObjectNotFoundException, SchemaException { ObjectType object = repositoryService.getObject(UserType.class, oid, - null, new OperationResult(OPERATION_GET_USER)).asObjectable(); + null, result).asObjectable(); if (object != null && (object instanceof UserType)) { return (UserType) object; } diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java index 2a0028a157a..3e11d88c730 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentEvaluator.java @@ -150,6 +150,8 @@ public void testDirect() throws Exception { Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); display("Evaluated construction", construction); assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); } @Test @@ -189,6 +191,8 @@ public void testDirectExpression() throws Exception { Construction construction = evaluatedAssignment.getConstructions().getZeroSet().iterator().next(); assertNotNull("No object class definition in construction", construction.getRefinedObjectClassDefinition()); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); } @Test @@ -255,6 +259,8 @@ public void testDirectExpressionReplaceDescription() throws Exception { assertConstruction(evaluatedAssignment, ZERO, "title", MINUS, "The best pirate the world has ever seen"); assertNoConstruction(evaluatedAssignment, PLUS, "title"); assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); } @Test @@ -322,6 +328,8 @@ public void testDirectExpressionReplaceDescriptionFromNull() throws Exception { assertConstruction(evaluatedAssignment, ZERO, "title", MINUS, "The best man the world has ever seen"); assertNoConstruction(evaluatedAssignment, PLUS, "title"); assertNoConstruction(evaluatedAssignment, MINUS, "title"); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); } /* @@ -392,6 +400,8 @@ public void testRoleVisitor() throws Exception { assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); assertNoConstruction(evaluatedAssignment, PLUS, "location"); assertNoConstruction(evaluatedAssignment, MINUS, "location"); + + assertEquals("Wrong number of admin GUI configs", 0, evaluatedAssignment.getAdminGuiConfigurations().size()); } @Test @@ -440,6 +450,8 @@ public void testRoleEngineer() throws Exception { assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); assertNoConstruction(evaluatedAssignment, PLUS, "location"); assertNoConstruction(evaluatedAssignment, MINUS, "location"); + + assertEquals("Wrong number of admin GUI configs", 1, evaluatedAssignment.getAdminGuiConfigurations().size()); } @Test @@ -478,7 +490,7 @@ public void testAddRoleEngineer() throws Exception { assertNotNull(evaluatedAssignment); display("Evaluated assignment",evaluatedAssignment.debugDump()); - assertEquals(4, evaluatedAssignment.getConstructions().size()); + assertEquals("Wrong number of constructions", 4, evaluatedAssignment.getConstructions().size()); PrismAsserts.assertParentConsistency(userTypeJack.asPrismObject()); /* @@ -505,6 +517,8 @@ public void testAddRoleEngineer() throws Exception { assertConstruction(evaluatedAssignment, ZERO, "location", MINUS); assertNoConstruction(evaluatedAssignment, PLUS, "location"); assertNoConstruction(evaluatedAssignment, MINUS, "location"); + + assertEquals("Wrong number of admin GUI configs", 1, evaluatedAssignment.getAdminGuiConfigurations().size()); } /** diff --git a/model/model-impl/src/test/resources/lens/role-corp-engineer.xml b/model/model-impl/src/test/resources/lens/role-corp-engineer.xml index 5f5b94525c5..53fe43a8b8a 100644 --- a/model/model-impl/src/test/resources/lens/role-corp-engineer.xml +++ b/model/model-impl/src/test/resources/lens/role-corp-engineer.xml @@ -31,5 +31,23 @@ http://midpoint.evolveum.com/xml/ns/test/authorization#design true + + + http://example.com/englib + + + + http://example.com/engloop + + + + + UserType + + com.example.form.FooPanel + + + + job diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestPreviewChanges.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestPreviewChanges.java index 78e18e00dcd..95145c5607c 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestPreviewChanges.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestPreviewChanges.java @@ -464,8 +464,7 @@ public void test130GetAdminGuiConfig() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); - assertNotNull("Null config", adminGuiConfiguration); - assertEquals("Unexpected number of links", 1, adminGuiConfiguration.getUserDashboardLink().size()); + assertAdminGuiConfigurations(adminGuiConfiguration, 0, 1, 1); RichHyperlinkType link = adminGuiConfiguration.getUserDashboardLink().get(0); assertEquals("Bad link label", "Foo", link.getLabel()); assertEquals("Bad link targetUrl", "/foo", link.getTargetUrl()); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java index a04a49fd59b..a1e3e21d856 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java @@ -499,6 +499,8 @@ public void test100JackRolePirate() throws Exception { assertNotAuthorized(principal, AUTZ_LOOT_URL, AuthorizationPhaseType.REQUEST); assertNotAuthorized(principal, AUTZ_LOOT_URL, null); assertNotAuthorized(principal, AUTZ_COMMAND_URL); + + assertAdminGuiConfigurations(principal, 1, 2, 2); } @Test @@ -523,6 +525,8 @@ public void test109JackUnassignRolePirate() throws Exception { assertNotAuthorized(principal, AUTZ_LOOT_URL); assertNotAuthorized(principal, AUTZ_COMMAND_URL); + + assertAdminGuiConfigurations(principal, 0, 1, 1); } @Test diff --git a/model/model-intest/src/test/resources/common/role-pirate.xml b/model/model-intest/src/test/resources/common/role-pirate.xml index 7aa4ad7f59c..158f838685e 100644 --- a/model/model-intest/src/test/resources/common/role-pirate.xml +++ b/model/model-intest/src/test/resources/common/role-pirate.xml @@ -1,5 +1,5 @@ + + + +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java index a7813ee8cd6..6e4a76d9fd5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java @@ -11,6 +11,8 @@ import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.prism.ItemWrapper; +import com.evolveum.midpoint.web.component.prism.ValueWrapper; import com.evolveum.midpoint.web.component.util.SimplePanel; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPage; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPanel; @@ -25,9 +27,11 @@ import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; +import org.apache.wicket.model.PropertyModel; import java.util.ArrayList; import java.util.Collection; @@ -54,19 +58,21 @@ public class AssociationValueChoosePanel extends Simpl private static final String ID_ADD = "add"; private static final String ID_REMOVE = "remove"; private static final String ID_BUTTON_GROUP = "buttonGroup"; - private static final String ID_EDIT = "edit"; +// private static final String ID_EDIT = "edit"; +private IModel model; protected static final String MODAL_ID_OBJECT_SELECTION_POPUP = "objectSelectionPopup"; private ObjectQuery query = null; - public AssociationValueChoosePanel(String id, IModel value, List values, boolean required, Class type, + public AssociationValueChoosePanel(String id, IModel model, List values, boolean required, Class type, ObjectQuery query){ - super(id, value); + super(id, (IModel)new PropertyModel<>(model, "value")); + this.model = model; this.query = query; setOutputMarkupId(true); - initLayout(value, values, required, type); + initLayout((IModel)new PropertyModel<>(model, "value"), values, required, type); } private void initLayout(final IModel value, final List values, @@ -90,14 +96,14 @@ protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { FeedbackPanel feedback = new FeedbackPanel(ID_FEEDBACK, new ComponentFeedbackMessageFilter(text)); textWrapper.add(feedback); - AjaxLink edit = new AjaxLink(ID_EDIT) { - - @Override - public void onClick(AjaxRequestTarget target) { - editValuePerformed(values, target); - } - }; - textWrapper.add(edit); +// AjaxLink edit = new AjaxLink(ID_EDIT) { +// +// @Override +// public void onClick(AjaxRequestTarget target) { +// editValuePerformed(values, target); +// } +// }; +// textWrapper.add(edit); add(textWrapper); initDialog(type, values); @@ -162,8 +168,7 @@ public Collection> getDataProviderOptions() @Override public ObjectQuery getDataProviderQuery() { - - return getRealParent().createChooseQuery(values); + return query; } @Override @@ -277,34 +282,31 @@ public String getObject() { }; } - protected void editValuePerformed(List values, AjaxRequestTarget target) { + public void editValuePerformed(AjaxRequestTarget target) { ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); window.show(target); - ObjectSelectionPanel dialog = (ObjectSelectionPanel) window.get(createComponentPath(window.getContentId(), ObjectSelectionPage.ID_OBJECT_SELECTION_PANEL)); - if (dialog != null) { - dialog.updateTablePerformed(target, createChooseQuery(values)); - } +// ObjectSelectionPanel dialog = (ObjectSelectionPanel) window.get(createComponentPath(window.getContentId(), ObjectSelectionPage.ID_OBJECT_SELECTION_PANEL)); +// if (dialog != null) { +// dialog.updateTablePerformed(target, createChooseQuery(values)); +// } } - /* - * TODO - this method contains check, if chosen object already is not in - * selected values array This is a temporary solution until we well be able - * to create "already-chosen" query - */ protected void choosePerformed(AjaxRequestTarget target, C object) { - choosePerformedHook(target, object); ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); window.close(target); - if(isObjectUnique(object)){ + ValueWrapper wrapper = model.getObject(); + ItemWrapper propertyWrapper = wrapper.getItem(); + propertyWrapper.addValue(); + + ListView parent = findParent(ListView.class).findParent(ListView.class); + target.add(parent.getParent()); + replaceIfEmpty(object); - } if (LOGGER.isTraceEnabled()) { LOGGER.trace("New object instance has been added to the model."); } - // has to be done in the context of parent page - //target.add(this); } From 9558cf918e805b294947962be30eb73bb83453ed Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 9 Dec 2015 15:14:03 +0100 Subject: [PATCH 084/116] A couple of new cert-related tests and fixes (repo). --- .../midpoint/prism/PrismContainerValue.java | 4 + .../midpoint/repo/sql/CertificationTest.java | 156 ++++++++++++++++-- .../test/resources/cert/cert-campaign-2.xml | 77 +++++++++ .../RAccessCertificationDecision.java | 11 +- .../sql/helpers/CertificationCaseHelper.java | 5 + 5 files changed, 238 insertions(+), 15 deletions(-) create mode 100644 repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-2.xml diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java index 58727c31873..2922f09a705 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java @@ -511,6 +511,10 @@ public boolean contains(Item item) { } return false; } + + public boolean contains(QName itemName) { + return findItem(itemName) != null; + } @Override public Object find(ItemPath path) { diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java index 388f582eb14..56a63cc3a09 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java @@ -20,11 +20,12 @@ import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.prism.util.CloneUtil; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.repo.api.RepoAddOptions; @@ -32,7 +33,6 @@ import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -41,7 +41,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; @@ -51,7 +50,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.List; import static com.evolveum.midpoint.prism.delta.PropertyDelta.createModificationReplaceProperty; @@ -84,8 +82,10 @@ public class CertificationTest extends BaseSQLRepoTest { private static final Trace LOGGER = TraceManager.getTrace(CertificationTest.class); private static final File TEST_DIR = new File("src/test/resources/cert"); public static final File CAMPAIGN_1_FILE = new File(TEST_DIR, "cert-campaign-1.xml"); + public static final File CAMPAIGN_2_FILE = new File(TEST_DIR, "cert-campaign-2.xml"); - private String campaignOid; + private String campaign1Oid; + private String campaign2Oid; private PrismObjectDefinition campaignDef; @Test @@ -95,12 +95,12 @@ public void test100AddCampaignNonOverwrite() throws Exception { OperationResult result = new OperationResult("test100AddCampaignNonOverwrite"); - campaignOid = repositoryService.addObject(campaign, null, result); + campaign1Oid = repositoryService.addObject(campaign, null, result); result.recomputeStatus(); AssertJUnit.assertTrue(result.isSuccess()); - checkCampaign(campaignOid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); } @Test(expectedExceptions = ObjectAlreadyExistsException.class) @@ -114,10 +114,10 @@ public void test105AddCampaignNonOverwriteExisting() throws Exception { public void test108AddCampaignOverwriteExisting() throws Exception { PrismObject campaign = prismContext.parseObject(CAMPAIGN_1_FILE); OperationResult result = new OperationResult("test108AddCampaignOverwriteExisting"); - campaign.setOid(campaignOid); // doesn't work without specifying OID - campaignOid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); + campaign.setOid(campaign1Oid); // doesn't work without specifying OID + campaign1Oid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); - checkCampaign(campaignOid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); } @Test @@ -277,22 +277,150 @@ public void test250AddDeleteModifyResponse() throws Exception { executeAndCheckModification(modifications, result); } + @Test + public void test260ReplaceDecisionsExistingId() throws Exception { + OperationResult result = new OperationResult("test260ReplaceDecisions"); + + AccessCertificationDecisionType dec200 = new AccessCertificationDecisionType(prismContext); + dec200.setId(200L); + dec200.setStageNumber(44); + dec200.setReviewerRef(createObjectRef("999999", ObjectTypes.USER)); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE, 6, F_DECISION).replace(dec200) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test265ReplaceDecisionsNewId() throws Exception { + OperationResult result = new OperationResult("test265ReplaceDecisions"); + + AccessCertificationDecisionType dec250 = new AccessCertificationDecisionType(prismContext); + dec250.setId(250L); + dec250.setStageNumber(440); + dec250.setReviewerRef(createObjectRef("250-999999", ObjectTypes.USER)); + + AccessCertificationDecisionType dec251 = new AccessCertificationDecisionType(prismContext); + dec251.setId(251L); + dec251.setStageNumber(1); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE, 6, F_DECISION).replace(dec250, dec251) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test270ReplaceCase() throws Exception { + OperationResult result = new OperationResult("test270ReplaceCase"); + + AccessCertificationDecisionType dec777 = new AccessCertificationDecisionType(prismContext); + dec777.setId(777L); + dec777.setStageNumber(888); + dec777.setReviewerRef(createObjectRef("999", ObjectTypes.USER)); + + AccessCertificationDecisionType decNoId = new AccessCertificationDecisionType(prismContext); + decNoId.setStageNumber(889); + decNoId.setReviewerRef(createObjectRef("9999", ObjectTypes.USER)); + + AccessCertificationCaseType caseNoId = new AccessCertificationCaseType(prismContext); + caseNoId.setObjectRef(createObjectRef("aaa", ObjectTypes.USER)); + caseNoId.setTargetRef(createObjectRef("bbb", ObjectTypes.ROLE)); + caseNoId.getReviewerRef().add(createObjectRef("ccc", ObjectTypes.USER)); + caseNoId.setCurrentStageNumber(1); + caseNoId.getDecision().add(dec777); + caseNoId.getDecision().add(decNoId); + + List modifications = DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, prismContext) + .item(F_CASE).replace(caseNoId) + .asItemDeltas(); + + executeAndCheckModification(modifications, result); + } + + @Test + public void test300PrepareForQueryCases() throws Exception { + OperationResult result = new OperationResult("test300QueryCases"); + + // overwrite the campaign + PrismObject campaign = prismContext.parseObject(CAMPAIGN_1_FILE); + campaign.setOid(campaign1Oid); // doesn't work without specifying OID + campaign1Oid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); + + checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + + PrismObject campaign2 = prismContext.parseObject(CAMPAIGN_2_FILE); + campaign2Oid = repositoryService.addObject(campaign2, null, result); + + checkCampaign(campaign2Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_2_FILE), null); + } + + @Test + public void test310CasesForCampaign() throws Exception { + OperationResult result = new OperationResult("test310CasesForCampaign"); + + checkCasesForCampaign(campaign1Oid, result); + checkCasesForCampaign(campaign2Oid, result); + } + + @Test + public void test320AllCases() throws Exception { + OperationResult result = new OperationResult("test320AllCases"); + + List cases = repositoryService.searchContainers(AccessCertificationCaseType.class, null, null, result); + + AccessCertificationCampaignType campaign1 = getFullCampaign(campaign1Oid, result).asObjectable(); + AccessCertificationCampaignType campaign2 = getFullCampaign(campaign2Oid, result).asObjectable(); + List expectedCases = new ArrayList<>(); + expectedCases.addAll(campaign1.getCase()); + expectedCases.addAll(campaign2.getCase()); + PrismAsserts.assertEqualsCollectionUnordered("list of cases is different", cases, expectedCases.toArray(new AccessCertificationCaseType[0])); + } + +// @Test +// public void test330CurrentUnansweredCases() throws Exception { +// OperationResult result = new OperationResult("test330CurrentUnansweredCases"); +// +// List cases = repositoryService.searchContainers(AccessCertificationCaseType.class, null, null, result); +// +// AccessCertificationCampaignType campaign1 = getFullCampaign(campaign1Oid, result).asObjectable(); +// AccessCertificationCampaignType campaign2 = getFullCampaign(campaign2Oid, result).asObjectable(); +// List expectedCases = new ArrayList<>(); +// expectedCases.addAll(campaign1.getCase()); +// expectedCases.addAll(campaign2.getCase()); +// PrismAsserts.assertEqualsCollectionUnordered("list of cases is different", cases, expectedCases.toArray(new AccessCertificationCaseType[0])); +// } + + private void checkCasesForCampaign(String oid, OperationResult result) throws SchemaException, ObjectNotFoundException { + ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) + .ownerId(oid) + .build(); + List cases = repositoryService.searchContainers(AccessCertificationCaseType.class, query, null, result); + for (AccessCertificationCaseType aCase : cases) { + AssertJUnit.assertEquals("wrong campaign ref", oid, aCase.getCampaignRef().getOid()); + } + AccessCertificationCampaignType campaign = getFullCampaign(oid, result).asObjectable(); + PrismAsserts.assertEqualsCollectionUnordered("list of cases is different", cases, campaign.getCase().toArray(new AccessCertificationCaseType[0])); + } @Test public void test900DeleteCampaign() throws Exception { OperationResult result = new OperationResult("test900DeleteCampaign"); - repositoryService.deleteObject(AccessCertificationCampaignType.class, campaignOid, result); + repositoryService.deleteObject(AccessCertificationCampaignType.class, campaign1Oid, result); result.recomputeStatus(); AssertJUnit.assertTrue(result.isSuccess()); } protected void executeAndCheckModification(List modifications, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, IOException { - PrismObject before = getFullCampaign(campaignOid, result); + PrismObject before = getFullCampaign(campaign1Oid, result); List savedModifications = (List) CloneUtil.cloneCollectionMembers(modifications); - repositoryService.modifyObject(AccessCertificationCampaignType.class, campaignOid, modifications, result); + repositoryService.modifyObject(AccessCertificationCampaignType.class, campaign1Oid, modifications, result); - checkCampaign(campaignOid, result, before, savedModifications); + checkCampaign(campaign1Oid, result, before, savedModifications); } private void checkCampaign(String campaignOid, OperationResult result, PrismObject expectedObject, List modifications) throws SchemaException, ObjectNotFoundException, IOException { diff --git a/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-2.xml b/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-2.xml new file mode 100644 index 00000000000..685d8cbe207 --- /dev/null +++ b/repo/repo-sql-impl-test/src/test/resources/cert/cert-campaign-2.xml @@ -0,0 +1,77 @@ + + + + + + All user assignments 2 + Certifies all users' assignments. Everything is certified by the administrator. + + + http://midpoint.evolveum.com/xml/ns/public/certification/handlers-3#direct-assignment + + 1 + Administrator's review + In this stage, the administrator has to review all the assignments of all users. + 14 + 48 + 12 + true + + + + + 2015-12-04T00:38:03.031+01:00 + inReviewStage + 1 + + 1 + Administrator's review + In this stage, the administrator has to review all the assignments of all users. + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + + + + + + 2015-12-04T00:38:00.708+01:00 + 2015-12-18T23:59:59.999+01:00 + + 1 + + accept + 2015-12-04T01:10:20.032+01:00 + + accept + 1 + + + + false + + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java index d807a272ab7..0160c268121 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java @@ -32,6 +32,8 @@ import javax.persistence.*; import javax.xml.datatype.XMLGregorianCalendar; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_STAGE_NUMBER; + /** * Although being an image of a Containerable, this class is not a container in the sense of Container class: * its owner is not a RObject. @@ -186,7 +188,14 @@ public static RAccessCertificationDecision toRepo(RAccessCertificationCase ownin private static RAccessCertificationDecision toRepo(AccessCertificationDecisionType decision, PrismContext prismContext) { RAccessCertificationDecision rDecision = new RAccessCertificationDecision(); rDecision.setTransient(null); // we don't try to advise hibernate - let it do its work, even if it would cost some SELECTs - rDecision.setId(RUtil.toInteger(decision.getId())); + Integer idInt = RUtil.toInteger(decision.getId()); + if (idInt == null) { + throw new IllegalArgumentException("No ID for access certification decision: " + decision); + } + rDecision.setId(idInt); + if (!decision.asPrismContainerValue().contains(F_STAGE_NUMBER)) { // this check should be part of prism container maybe + throw new IllegalArgumentException("No stage number for access certification decision: " + decision); + } rDecision.setStageNumber(decision.getStageNumber()); rDecision.setReviewerRef(RUtil.jaxbRefToEmbeddedRepoRef(decision.getReviewerRef(), prismContext)); rDecision.setResponse(RUtil.getRepoEnumValue(decision.getResponse(), RAccessCertificationResponse.class)); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index d2ddd9c232d..7840c1b1e2b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -103,6 +103,11 @@ public void addCertificationCampaignCases(Session session, String campaignOid, C caseType.setId((long) currentId); currentId++; } + + // we need to generate IDs but we (currently) do not use that for setting "isTransient" flag + PrismIdentifierGenerator generator = new PrismIdentifierGenerator(); + generator.generate(caseType, PrismIdentifierGenerator.Operation.MODIFY); + RAccessCertificationCase row = RAccessCertificationCase.toRepo(campaignOid, caseType, prismContext); row.setId(RUtil.toInteger(caseType.getId())); affectedIds.add(caseType.getId()); From c18083cd1112fb7df10655016b56b021579df662 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Wed, 9 Dec 2015 15:47:20 +0100 Subject: [PATCH 085/116] Fixing inbound and null values (MID-2421) +tests --- .../impl/lens/projector/InboundProcessor.java | 2 +- .../intest/sync/AbstractInboundSyncTest.java | 336 ++++++++++++++++++ .../src/test/resources/logback-test.xml | 6 +- .../resource-dummy-emerald-deprecated.xml | 31 +- .../resources/sync/resource-dummy-emerald.xml | 31 +- 5 files changed, 400 insertions(+), 6 deletions(-) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java index d4e28b1e5eb..00999acc264 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java @@ -432,7 +432,7 @@ private PropertyDelta evaluateInboundMapping(final LOGGER.trace("Inbound value construction for {} returned triple:\n{}", accountAttributeName, triple == null ? "null" : triple.debugDump()); } - if (triple != null) { + if (triple != null && !triple.isEmpty()) { if (triple.hasPlusSet()) { diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractInboundSyncTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractInboundSyncTest.java index 3518b590eb2..8c11aece611 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractInboundSyncTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractInboundSyncTest.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.FileNotFoundException; +import java.util.ArrayList; import java.util.Date; import javax.xml.datatype.XMLGregorianCalendar; @@ -34,6 +35,8 @@ import com.evolveum.icf.dummy.resource.DummyResource; import com.evolveum.midpoint.model.intest.AbstractInitializedModelIntegrationTest; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.result.OperationResult; @@ -191,6 +194,339 @@ public void test110AddDummyEmeraldAccountMancomb() throws Exception { // notifications notificationManager.setDisabled(true); } + + @Test + public void test120ModifyDummyEmeraldAccountMancombSeepbad() throws Exception { + final String TEST_NAME = "test120ModifyDummyEmeraldAccountMancombSeepbad"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractInboundSyncTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + rememberTimeBeforeSync(); + prepareNotifications(); + + // Preconditions + assertUsers(6); + + DummyAccount account = dummyResourceEmerald.getAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + + /// WHEN + TestUtil.displayWhen(TEST_NAME); + + account.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepbad"); + + display("Modified dummy account", account.debugDump()); + + waitForSyncTaskNextRun(resourceDummyEmerald); + + // THEN + TestUtil.displayThen(TEST_NAME); + + PrismObject accountAfter = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyEmerald); + display("Account mancomb", accountAfter); + assertNotNull("No mancomb account shadow", accountAfter); + assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_EMERALD_OID, + accountAfter.asObjectable().getResourceRef().getOid()); + assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); + assertDummyAccountAttribute(RESOURCE_DUMMY_EMERALD_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepbad"); + + PrismObject userAfter = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + display("User mancomb", userAfter); + assertNotNull("User mancomb was not created", userAfter); + assertLinks(userAfter, 1); + assertAdministrativeStatusEnabled(userAfter); + assertValidFrom(userAfter, ACCOUNT_MANCOMB_VALID_FROM_DATE); + assertValidTo(userAfter, ACCOUNT_MANCOMB_VALID_TO_DATE); + + assertLinked(userAfter, accountAfter); + + PrismAsserts.assertPropertyValue(userAfter, UserType.F_FULL_NAME, PrismTestUtil.createPolyString("Mancomb Seepbad")); + + assertUsers(6); + + // notifications + notificationManager.setDisabled(true); + } + + @Test + public void test122ModifyDummyEmeraldAccountMancombSeepNULL() throws Exception { + final String TEST_NAME = "test122ModifyDummyEmeraldAccountMancombSeepNULL"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractInboundSyncTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + rememberTimeBeforeSync(); + prepareNotifications(); + + // Preconditions + assertUsers(6); + + DummyAccount account = dummyResourceEmerald.getAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + + /// WHEN + TestUtil.displayWhen(TEST_NAME); + + account.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb SeepNULL"); + + display("Modified dummy account", account.debugDump()); + + waitForSyncTaskNextRun(resourceDummyEmerald); + + // THEN + TestUtil.displayThen(TEST_NAME); + + PrismObject accountAfter = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyEmerald); + display("Account mancomb", accountAfter); + assertNotNull("No mancomb account shadow", accountAfter); + assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_EMERALD_OID, + accountAfter.asObjectable().getResourceRef().getOid()); + assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); + assertDummyAccountAttribute(RESOURCE_DUMMY_EMERALD_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb SeepNULL"); + + PrismObject userAfter = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + display("User mancomb", userAfter); + assertNotNull("User mancomb was not created", userAfter); + assertLinks(userAfter, 1); + assertAdministrativeStatusEnabled(userAfter); + assertValidFrom(userAfter, ACCOUNT_MANCOMB_VALID_FROM_DATE); + assertValidTo(userAfter, ACCOUNT_MANCOMB_VALID_TO_DATE); + + assertLinked(userAfter, accountAfter); + + PrismAsserts.assertNoItem(userAfter, UserType.F_FULL_NAME); + + assertUsers(6); + + // notifications + notificationManager.setDisabled(true); + } + + @Test + public void test124ModifyDummyEmeraldAccountMancombSeepevil() throws Exception { + final String TEST_NAME = "test124ModifyDummyEmeraldAccountMancombSeepevil"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractInboundSyncTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + rememberTimeBeforeSync(); + prepareNotifications(); + + // Preconditions + assertUsers(6); + + DummyAccount account = dummyResourceEmerald.getAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + + /// WHEN + TestUtil.displayWhen(TEST_NAME); + + account.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepevil"); + + display("Modified dummy account", account.debugDump()); + + waitForSyncTaskNextRun(resourceDummyEmerald); + + // THEN + TestUtil.displayThen(TEST_NAME); + + PrismObject accountAfter = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyEmerald); + display("Account mancomb", accountAfter); + assertNotNull("No mancomb account shadow", accountAfter); + assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_EMERALD_OID, + accountAfter.asObjectable().getResourceRef().getOid()); + assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); + assertDummyAccountAttribute(RESOURCE_DUMMY_EMERALD_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepevil"); + + PrismObject userAfter = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + display("User mancomb", userAfter); + assertNotNull("User mancomb was not created", userAfter); + assertLinks(userAfter, 1); + assertAdministrativeStatusEnabled(userAfter); + assertValidFrom(userAfter, ACCOUNT_MANCOMB_VALID_FROM_DATE); + assertValidTo(userAfter, ACCOUNT_MANCOMB_VALID_TO_DATE); + + assertLinked(userAfter, accountAfter); + + PrismAsserts.assertPropertyValue(userAfter, UserType.F_FULL_NAME, PrismTestUtil.createPolyString("Mancomb Seepevil")); + + assertUsers(6); + + // notifications + notificationManager.setDisabled(true); + } + + @Test + public void test126ModifyDummyEmeraldAccountMancombTitlePirate() throws Exception { + final String TEST_NAME = "test126ModifyDummyEmeraldAccountMancombTitlePirate"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractInboundSyncTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + rememberTimeBeforeSync(); + prepareNotifications(); + + // Preconditions + assertUsers(6); + + DummyAccount account = dummyResourceEmerald.getAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + + /// WHEN + TestUtil.displayWhen(TEST_NAME); + + account.replaceAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, "Pirate"); + + display("Modified dummy account", account.debugDump()); + + waitForSyncTaskNextRun(resourceDummyEmerald); + + // THEN + TestUtil.displayThen(TEST_NAME); + + PrismObject accountAfter = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyEmerald); + display("Account mancomb", accountAfter); + assertNotNull("No mancomb account shadow", accountAfter); + assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_EMERALD_OID, + accountAfter.asObjectable().getResourceRef().getOid()); + assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); + assertDummyAccountAttribute(RESOURCE_DUMMY_EMERALD_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, "Pirate"); + + PrismObject userAfter = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + display("User mancomb", userAfter); + assertNotNull("User mancomb was not created", userAfter); + assertLinks(userAfter, 1); + assertAdministrativeStatusEnabled(userAfter); + assertValidFrom(userAfter, ACCOUNT_MANCOMB_VALID_FROM_DATE); + assertValidTo(userAfter, ACCOUNT_MANCOMB_VALID_TO_DATE); + + assertLinked(userAfter, accountAfter); + + PrismAsserts.assertPropertyValue(userAfter, UserType.F_FULL_NAME, PrismTestUtil.createPolyString("Mancomb Seepevil")); + PrismAsserts.assertPropertyValue(userAfter, UserType.F_TITLE, PrismTestUtil.createPolyString("Pirate")); + + assertUsers(6); + + // notifications + notificationManager.setDisabled(true); + } + + @Test + public void test127ModifyDummyEmeraldAccountMancombTitlePirateNull() throws Exception { + final String TEST_NAME = "test127ModifyDummyEmeraldAccountMancombTitlePirateNull"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractInboundSyncTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + rememberTimeBeforeSync(); + prepareNotifications(); + + // Preconditions + assertUsers(6); + + DummyAccount account = dummyResourceEmerald.getAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + + /// WHEN + TestUtil.displayWhen(TEST_NAME); + + account.replaceAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME); + + display("Modified dummy account", account.debugDump()); + + waitForSyncTaskNextRun(resourceDummyEmerald); + + // THEN + TestUtil.displayThen(TEST_NAME); + + PrismObject accountAfter = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyEmerald); + display("Account mancomb", accountAfter); + assertNotNull("No mancomb account shadow", accountAfter); + assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_EMERALD_OID, + accountAfter.asObjectable().getResourceRef().getOid()); + assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); + assertDummyAccountAttribute(RESOURCE_DUMMY_EMERALD_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME); + + PrismObject userAfter = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + display("User mancomb", userAfter); + assertNotNull("User mancomb was not created", userAfter); + assertLinks(userAfter, 1); + assertAdministrativeStatusEnabled(userAfter); + assertValidFrom(userAfter, ACCOUNT_MANCOMB_VALID_FROM_DATE); + assertValidTo(userAfter, ACCOUNT_MANCOMB_VALID_TO_DATE); + + assertLinked(userAfter, accountAfter); + + PrismAsserts.assertPropertyValue(userAfter, UserType.F_FULL_NAME, PrismTestUtil.createPolyString("Mancomb Seepevil")); + PrismAsserts.assertNoItem(userAfter, UserType.F_TITLE); + + assertUsers(6); + + // notifications + notificationManager.setDisabled(true); + } + + @Test + public void test129ModifyDummyEmeraldAccountMancombSeepgood() throws Exception { + final String TEST_NAME = "test129ModifyDummyEmeraldAccountMancombSeepgood"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(AbstractInboundSyncTest.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + rememberTimeBeforeSync(); + prepareNotifications(); + + // Preconditions + assertUsers(6); + + DummyAccount account = dummyResourceEmerald.getAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + + /// WHEN + TestUtil.displayWhen(TEST_NAME); + + account.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepgood"); + + display("Modified dummy account", account.debugDump()); + + waitForSyncTaskNextRun(resourceDummyEmerald); + + // THEN + TestUtil.displayThen(TEST_NAME); + + PrismObject accountAfter = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyEmerald); + display("Account mancomb", accountAfter); + assertNotNull("No mancomb account shadow", accountAfter); + assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_EMERALD_OID, + accountAfter.asObjectable().getResourceRef().getOid()); + assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); + assertDummyAccountAttribute(RESOURCE_DUMMY_EMERALD_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepgood"); + + PrismObject userAfter = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + display("User mancomb", userAfter); + assertNotNull("User mancomb was not created", userAfter); + assertLinks(userAfter, 1); + assertAdministrativeStatusEnabled(userAfter); + assertValidFrom(userAfter, ACCOUNT_MANCOMB_VALID_FROM_DATE); + assertValidTo(userAfter, ACCOUNT_MANCOMB_VALID_TO_DATE); + + assertLinked(userAfter, accountAfter); + + PrismAsserts.assertPropertyValue(userAfter, UserType.F_FULL_NAME, PrismTestUtil.createPolyString("Mancomb Seepgood")); + + assertUsers(6); + + // notifications + notificationManager.setDisabled(true); + } + @Test public void test180NoChange() throws Exception { diff --git a/model/model-intest/src/test/resources/logback-test.xml b/model/model-intest/src/test/resources/logback-test.xml index e81b8c4badb..6859fc9b0e5 100644 --- a/model/model-intest/src/test/resources/logback-test.xml +++ b/model/model-intest/src/test/resources/logback-test.xml @@ -44,10 +44,10 @@ - - + + - + diff --git a/model/model-intest/src/test/resources/sync/resource-dummy-emerald-deprecated.xml b/model/model-intest/src/test/resources/sync/resource-dummy-emerald-deprecated.xml index 471d3316b19..2323fbb8fec 100644 --- a/model/model-intest/src/test/resources/sync/resource-dummy-emerald-deprecated.xml +++ b/model/model-intest/src/test/resources/sync/resource-dummy-emerald-deprecated.xml @@ -1,6 +1,6 @@ - notDecided + noResponse 2015-12-04T01:10:20.032+01:00 notDecided @@ -129,8 +128,6 @@ 1 - noResponse - 2015-12-04T01:10:08.670+01:00 noResponse 1 diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java index 8582075ec37..8f3d3230158 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -25,6 +25,7 @@ import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.util.CloneUtil; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.repo.sql.SerializationRelatedException; @@ -341,8 +342,8 @@ public void modifyObjectAttempt(Class type, String oid OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SerializationRelatedException { - // shallow clone - because some methods, e.g. filterLookupTableModifications manipulate this collection - modifications = new ArrayList<>(modifications); + // clone - because some methods, e.g. filterLookupTableModifications manipulate this collection + modifications = CloneUtil.cloneCollectionMembers(modifications); LOGGER.debug("Modifying object '{}' with oid '{}'.", new Object[]{type.getSimpleName(), oid}); LOGGER_PERFORMANCE.debug("> modify object {}, oid={}, modifications={}", type.getSimpleName(), oid, modifications); From 8c2703da77030a69ee688872989063402f0b1586 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 9 Dec 2015 20:06:22 +0100 Subject: [PATCH 087/116] Skipping owner object (campaign, lookup table) modification if there are no direct changes. --- .../midpoint/repo/sql/CertificationTest.java | 53 ++++---- .../midpoint/repo/sql/LookupTableTest.java | 30 +++-- .../repo-sql-impl-test/testng-integration.xml | 3 +- .../sql/helpers/CertificationCaseHelper.java | 15 +-- .../repo/sql/helpers/LookupTableHelper.java | 8 +- .../repo/sql/helpers/ObjectUpdater.java | 121 +++++++++--------- 6 files changed, 117 insertions(+), 113 deletions(-) diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java index 52c81124de8..37c24021b5b 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/CertificationTest.java @@ -76,7 +76,7 @@ import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_NAME; /** - * @author lazyman + * @author mederly */ @ContextConfiguration(locations = {"../../../../../ctx-test.xml"}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @@ -103,7 +103,7 @@ public void test100AddCampaignNonOverwrite() throws Exception { result.recomputeStatus(); AssertJUnit.assertTrue(result.isSuccess()); - checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null, null); } @Test(expectedExceptions = ObjectAlreadyExistsException.class) @@ -120,7 +120,7 @@ public void test108AddCampaignOverwriteExisting() throws Exception { campaign.setOid(campaign1Oid); // doesn't work without specifying OID campaign1Oid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); - checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null, null); } @Test @@ -131,7 +131,7 @@ public void test200ModifyCampaignProperties() throws Exception { modifications.add(createModificationReplaceProperty(F_NAME, campaignDef, new PolyString("Campaign 1+", "campaign 1"))); modifications.add(createModificationReplaceProperty(F_STATE, campaignDef, IN_REVIEW_STAGE)); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 1); } @Test @@ -143,7 +143,7 @@ public void test210ModifyCaseProperties() throws Exception { modifications.add(createModificationReplaceProperty(case1.subPath(F_CURRENT_RESPONSE), campaignDef, DELEGATE)); modifications.add(createModificationReplaceProperty(case1.subPath(F_CURRENT_STAGE_NUMBER), campaignDef, 300)); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -155,7 +155,7 @@ public void test220ModifyDecisionProperties() throws Exception { modifications.add(createModificationReplaceProperty(d1.subPath(F_RESPONSE), campaignDef, DELEGATE)); modifications.add(createModificationReplaceProperty(d1.subPath(F_COMMENT), campaignDef, "hi")); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -171,7 +171,7 @@ public void test230ModifyAllLevels() throws Exception { .item(F_CASE, 1, F_DECISION, 1, F_COMMENT).replace("low") .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 1); } @Test @@ -183,6 +183,7 @@ public void test240AddCases() throws Exception { caseNoId.setTargetRef(createObjectRef("456", ObjectTypes.ROLE)); caseNoId.setCurrentStageNumber(1); + // explicit ID is dangerous (possibility of conflict!) AccessCertificationCaseType case100 = new AccessCertificationCaseType(prismContext); case100.setId(100L); case100.setObjectRef(createObjectRef("100123", ObjectTypes.USER)); @@ -194,7 +195,7 @@ public void test240AddCases() throws Exception { .item(F_CASE).add(caseNoId, case100) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -208,7 +209,7 @@ public void test242DeleteCase() throws Exception { .item(F_CASE).delete(case7) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -224,7 +225,7 @@ public void test244ModifyCase() throws Exception { .item(F_CASE, 100, F_REVIEWER_REF).delete(reviewerToDelete) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @@ -237,6 +238,7 @@ public void test248AddDeleteModifyCase() throws Exception { caseNoId.setTargetRef(createObjectRef("x456", ObjectTypes.ROLE)); caseNoId.setCurrentStageNumber(1); + // explicit ID is dangerous AccessCertificationCaseType case110 = new AccessCertificationCaseType(prismContext); case110.setId(110L); case110.setObjectRef(createObjectRef("x100123", ObjectTypes.USER)); @@ -252,7 +254,7 @@ public void test248AddDeleteModifyCase() throws Exception { .item(F_CASE, 3, F_CURRENT_STAGE_NUMBER).replace(400) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -264,7 +266,7 @@ public void test250AddDeleteModifyResponse() throws Exception { decNoId.setStageNumber(1); AccessCertificationDecisionType dec200 = new AccessCertificationDecisionType(prismContext); - dec200.setId(200L); + dec200.setId(200L); // this is dangerous dec200.setStageNumber(1); dec200.setReviewerRef(createObjectRef("200888", ObjectTypes.USER)); @@ -277,7 +279,7 @@ public void test250AddDeleteModifyResponse() throws Exception { .item(F_CASE, 6, F_DECISION, 2, F_RESPONSE).replace(ACCEPT) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -285,7 +287,7 @@ public void test260ReplaceDecisionsExistingId() throws Exception { OperationResult result = new OperationResult("test260ReplaceDecisions"); AccessCertificationDecisionType dec200 = new AccessCertificationDecisionType(prismContext); - dec200.setId(200L); + dec200.setId(200L); //dangerous dec200.setStageNumber(44); dec200.setReviewerRef(createObjectRef("999999", ObjectTypes.USER)); @@ -293,7 +295,7 @@ public void test260ReplaceDecisionsExistingId() throws Exception { .item(F_CASE, 6, F_DECISION).replace(dec200) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -301,7 +303,7 @@ public void test265ReplaceDecisionsNewId() throws Exception { OperationResult result = new OperationResult("test265ReplaceDecisions"); AccessCertificationDecisionType dec250 = new AccessCertificationDecisionType(prismContext); - dec250.setId(250L); + dec250.setId(250L); //dangerous dec250.setStageNumber(440); dec250.setReviewerRef(createObjectRef("250-999999", ObjectTypes.USER)); @@ -313,13 +315,14 @@ public void test265ReplaceDecisionsNewId() throws Exception { .item(F_CASE, 6, F_DECISION).replace(dec250, dec251) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test public void test270ReplaceCase() throws Exception { OperationResult result = new OperationResult("test270ReplaceCase"); + // explicit ID is dangerous AccessCertificationDecisionType dec777 = new AccessCertificationDecisionType(prismContext); dec777.setId(777L); dec777.setStageNumber(888); @@ -341,7 +344,7 @@ public void test270ReplaceCase() throws Exception { .item(F_CASE).replace(caseNoId) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -353,12 +356,12 @@ public void test300PrepareForQueryCases() throws Exception { campaign.setOid(campaign1Oid); // doesn't work without specifying OID campaign1Oid = repositoryService.addObject(campaign, RepoAddOptions.createOverwrite(), result); - checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null); + checkCampaign(campaign1Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_1_FILE), null, null); PrismObject campaign2 = prismContext.parseObject(CAMPAIGN_2_FILE); campaign2Oid = repositoryService.addObject(campaign2, null, result); - checkCampaign(campaign2Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_2_FILE), null); + checkCampaign(campaign2Oid, result, (PrismObject) prismContext.parseObject(CAMPAIGN_2_FILE), null, null); } @Test @@ -460,16 +463,17 @@ public void test900DeleteCampaign() throws Exception { AssertJUnit.assertTrue(result.isSuccess()); } - protected void executeAndCheckModification(List modifications, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, IOException { + protected void executeAndCheckModification(List modifications, OperationResult result, int versionDelta) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, IOException { PrismObject before = getFullCampaign(campaign1Oid, result); + int expectedVersion = Integer.parseInt(before.getVersion()) + versionDelta; List savedModifications = (List) CloneUtil.cloneCollectionMembers(modifications); repositoryService.modifyObject(AccessCertificationCampaignType.class, campaign1Oid, modifications, result); - checkCampaign(campaign1Oid, result, before, savedModifications); + checkCampaign(campaign1Oid, result, before, savedModifications, expectedVersion); } - private void checkCampaign(String campaignOid, OperationResult result, PrismObject expectedObject, List modifications) throws SchemaException, ObjectNotFoundException, IOException { + private void checkCampaign(String campaignOid, OperationResult result, PrismObject expectedObject, List modifications, Integer expectedVersion) throws SchemaException, ObjectNotFoundException, IOException { expectedObject.setOid(campaignOid); if (modifications != null) { ItemDelta.applyTo(modifications, expectedObject); @@ -484,6 +488,9 @@ private void checkCampaign(String campaignOid, OperationResult result, PrismObje removeCampaignRef(expectedObject.asObjectable()); removeCampaignRef(campaign.asObjectable()); PrismAsserts.assertEquivalent("Campaign is not as expected", expectedObject, campaign); + if (expectedVersion != null) { + AssertJUnit.assertEquals("Incorrect version", (int) expectedVersion, Integer.parseInt(campaign.getVersion())); + } } private PrismObject getFullCampaign(String campaignOid, OperationResult result) throws ObjectNotFoundException, SchemaException { diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java index 1b671077c62..42875e84e39 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/LookupTableTest.java @@ -52,7 +52,7 @@ import static com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType.F_NAME; /** - * @author lazyman + * @author mederly */ @ContextConfiguration(locations = {"../../../../../ctx-test.xml"}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @@ -105,7 +105,7 @@ public void test200ModifyTableProperties() throws Exception { .item(F_NAME).replace(new PolyString("Table 1", "table 1")) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 1); } @Test(enabled = false) // row modification is not supported @@ -117,7 +117,7 @@ public void test210ModifyRowProperties() throws Exception { .item(F_ROW, 1, F_LAST_CHANGE_TIMESTAMP).replace() .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test(enabled = false) @@ -130,7 +130,7 @@ public void test230ModifyTableAndRow() throws Exception { .item(F_ROW, 2, F_VALUE).replace("value 2") .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 1); } @Test @@ -157,9 +157,9 @@ public void test240AddRows() throws Exception { .item(F_ROW).add(rowNoId, rowNoId2, row4) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); - // beware, ID for row4 was re-generated + // beware, ID for row4 was re-generated -- using client-provided IDs is not recommended anyway } @Test @@ -173,7 +173,7 @@ public void test242DeleteRow() throws Exception { .item(F_ROW).delete(row3) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test(enabled = false) @@ -195,7 +195,7 @@ public void test248AddDeleteModifyRows() throws Exception { .item(F_ROW).add(rowNoId, row5).delete(row4) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -203,7 +203,7 @@ public void test260ReplaceRowsExistingId() throws Exception { OperationResult result = new OperationResult("test260ReplaceRowsExistingId"); LookupTableRowType row5 = new LookupTableRowType(prismContext); - row5.setId(5L); + row5.setId(5L); // dangerous row5.setKey("key 5 plus"); row5.setValue("value 5 plus"); row5.setLastChangeTimestamp(XmlTypeConverter.createXMLGregorianCalendar(new Date(99, 3, 10))); @@ -212,7 +212,7 @@ public void test260ReplaceRowsExistingId() throws Exception { .item(F_ROW).replace(row5) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -228,7 +228,7 @@ public void test265ReplaceRowsNewId() throws Exception { .item(F_ROW).replace(rowNoId) .asItemDeltas(); - executeAndCheckModification(modifications, result); + executeAndCheckModification(modifications, result, 0); } @Test @@ -246,15 +246,15 @@ private void checkTable(String tableOid, PrismObject expectedOb PrismAsserts.assertEquivalent("Table is not as expected", expectedObject, table); } - protected void executeAndCheckModification(List modifications, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, IOException { + protected void executeAndCheckModification(List modifications, OperationResult result, int versionDelta) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, IOException { PrismObject before = getFullTable(tableOid, result); repositoryService.modifyObject(LookupTableType.class, tableOid, modifications, result); - checkTable(tableOid, result, before, modifications); + checkTable(tableOid, result, before, modifications, Integer.parseInt(before.getVersion()) + versionDelta); } - private void checkTable(String oid, OperationResult result, PrismObject expectedObject, List modifications) throws SchemaException, ObjectNotFoundException, IOException { + private void checkTable(String oid, OperationResult result, PrismObject expectedObject, List modifications, int expectedVersion) throws SchemaException, ObjectNotFoundException, IOException { expectedObject.setOid(oid); if (modifications != null) { ItemDelta.applyTo(modifications, expectedObject); @@ -264,6 +264,8 @@ private void checkTable(String oid, OperationResult result, PrismObject table = getFullTable(oid, result); LOGGER.trace("Actual object from repo = \n{}", table.debugDump()); PrismAsserts.assertEquivalent("Table is not as expected", expectedObject, table); + + AssertJUnit.assertEquals("Incorrect version", expectedVersion, Integer.parseInt(table.getVersion())); } private PrismObject getFullTable(String oid, OperationResult result) throws ObjectNotFoundException, SchemaException { diff --git a/repo/repo-sql-impl-test/testng-integration.xml b/repo/repo-sql-impl-test/testng-integration.xml index abdc1668a9e..864619d9575 100644 --- a/repo/repo-sql-impl-test/testng-integration.xml +++ b/repo/repo-sql-impl-test/testng-integration.xml @@ -41,7 +41,8 @@ - + + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 7840c1b1e2b..93923220d50 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -84,7 +84,7 @@ public void addCertificationCampaignCases(Session session, RObject object, boole RAccessCertificationCampaign campaign = (RAccessCertificationCampaign) object; if (merge) { - LOGGER.info("Deleting existing cases for {}", campaign.getOid()); + LOGGER.trace("Deleting existing cases for {}", campaign.getOid()); deleteCertificationCampaignCases(session, campaign.getOid()); } if (campaign.getCase() != null) { @@ -154,18 +154,12 @@ public Collection filterCampaignCase return caseDelta; } - public void updateCampaignCases(Session session, RObject object, + public void updateCampaignCases(Session session, String campaignOid, Collection modifications) throws SchemaException, ObjectNotFoundException { if (modifications.isEmpty()) { return; } - if (!(object instanceof RAccessCertificationCampaign)) { - throw new IllegalStateException("Object being modified is not a RAccessCertificationCampaign; it is " + object.getClass()); - } - final RAccessCertificationCampaign rCampaign = (RAccessCertificationCampaign) object; - final String campaignOid = object.getOid(); - List casesAddedOrDeleted = addOrDeleteCases(session, campaignOid, modifications); LOGGER.trace("Cases added/deleted (null means REPLACE operation) = {}", casesAddedOrDeleted); @@ -182,8 +176,6 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle throw new IllegalStateException("Wrong campaign delta sneaked into updateCampaignCases: class=" + delta.getClass() + ", path=" + deltaPath); } - // TODO treat missing decision IDs somehow - if (deltaPath.size() == 1) { if (delta.getValuesToDelete() != null) { // todo do 'bulk' delete like delete from ... where oid=? and id in (...) @@ -210,6 +202,9 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle deleteCase.executeUpdate(); } } + // TODO generated IDs might conflict with client-provided ones + // also, client-provided IDs might conflict with those that are already in the database + // So it's safest not to provide any IDs by the client if (delta.getValuesToAdd() != null) { int currentId = generalHelper.findLastIdInRepo(session, campaignOid, "get.campaignCaseLastId") + 1; addCertificationCampaignCases(session, campaignOid, delta.getValuesToAdd(), currentId, affectedIds); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java index 8be7f41fe6d..0c890d98d71 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/LookupTableHelper.java @@ -111,17 +111,11 @@ public void deleteLookupTableRows(Session session, String oid) { query.executeUpdate(); } - public void updateLookupTableData(Session session, RObject object, Collection modifications) { + public void updateLookupTableData(Session session, String tableOid, Collection modifications) { if (modifications.isEmpty()) { return; } - if (!(object instanceof RLookupTable)) { - throw new IllegalStateException("Object being modified is not a LookupTable; it is " + object.getClass()); - } - final RLookupTable rLookupTable = (RLookupTable) object; - final String tableOid = object.getOid(); - for (ItemDelta delta : modifications) { if (!(delta instanceof ContainerDelta) || delta.getPath().size() != 1) { throw new IllegalStateException("Wrong table delta sneaked into updateLookupTableData: class=" + delta.getClass() + ", path=" + delta.getPath()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java index 8f3d3230158..291229c961d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -342,7 +342,7 @@ public void modifyObjectAttempt(Class type, String oid OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SerializationRelatedException { - // clone - because some methods, e.g. filterLookupTableModifications manipulate this collection + // clone - because some certification and lookup table related methods manipulate this collection and even their constituent deltas modifications = CloneUtil.cloneCollectionMembers(modifications); LOGGER.debug("Modifying object '{}' with oid '{}'.", new Object[]{type.getSimpleName(), oid}); @@ -361,71 +361,76 @@ public void modifyObjectAttempt(Class type, String oid Collection lookupTableModifications = lookupTableHelper.filterLookupTableModifications(type, modifications); Collection campaignCaseModifications = caseHelper.filterCampaignCaseModifications(type, modifications); - // JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big. - // Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo - // association. However, this leads to a strange problem when merging in-memory RFocus object with the database state: - // If in-memory RFocus object has no photo associated (because of lazy loading), then the associated RFocusPhoto is deleted. - // - // To prevent this behavior, we've set orphanRemoval to false. Fortunately, the remove operation on RFocus - // seems to be still cascaded to RFocusPhoto. What we have to implement ourselves, however, is removal of RFocusPhoto - // _without_ removing of RFocus. In order to know whether the photo has to be removed, we have to retrieve - // its value, apply the delta (e.g. if the delta is a DELETE VALUE X, we have to know whether X matches current - // value of the photo), and if the resulting value is empty, we have to manually delete the RFocusPhoto instance. - // - // So the first step is to retrieve the current value of photo - we obviously do this only if the modifications - // deal with the jpegPhoto property. - Collection> options; - boolean containsFocusPhotoModification = FocusType.class.isAssignableFrom(type) && containsPhotoModification(modifications); - if (containsFocusPhotoModification) { - options = Arrays.asList(SelectorOptions.create(FocusType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); - } else { - options = null; - } - - // TODO skip processing if there are no modifications other than row/case ones + if (!modifications.isEmpty()) { + + // JpegPhoto (RFocusPhoto) is a special kind of entity. First of all, it is lazily loaded, because photos are really big. + // Each RFocusPhoto naturally belongs to one RFocus, so it would be appropriate to set orphanRemoval=true for focus-photo + // association. However, this leads to a strange problem when merging in-memory RFocus object with the database state: + // If in-memory RFocus object has no photo associated (because of lazy loading), then the associated RFocusPhoto is deleted. + // + // To prevent this behavior, we've set orphanRemoval to false. Fortunately, the remove operation on RFocus + // seems to be still cascaded to RFocusPhoto. What we have to implement ourselves, however, is removal of RFocusPhoto + // _without_ removing of RFocus. In order to know whether the photo has to be removed, we have to retrieve + // its value, apply the delta (e.g. if the delta is a DELETE VALUE X, we have to know whether X matches current + // value of the photo), and if the resulting value is empty, we have to manually delete the RFocusPhoto instance. + // + // So the first step is to retrieve the current value of photo - we obviously do this only if the modifications + // deal with the jpegPhoto property. + Collection> options; + boolean containsFocusPhotoModification = FocusType.class.isAssignableFrom(type) && containsPhotoModification(modifications); + if (containsFocusPhotoModification) { + options = Arrays.asList(SelectorOptions.create(FocusType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); + } else { + options = null; + } - // get object - PrismObject prismObject = objectRetriever.getObjectInternal(session, type, oid, options, true); - // apply diff - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT before:\n{}", new Object[]{prismObject.debugDump()}); - } - PrismObject originalObject = null; - if (closureManager.isEnabled()) { - originalObject = prismObject.clone(); - } - ItemDelta.applyTo(modifications, prismObject); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("OBJECT after:\n{}", prismObject.debugDump()); - } + // get object + PrismObject prismObject = objectRetriever.getObjectInternal(session, type, oid, options, true); + // apply diff + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT before:\n{}", new Object[]{prismObject.debugDump()}); + } + PrismObject originalObject = null; + if (closureManager.isEnabled()) { + originalObject = prismObject.clone(); + } + ItemDelta.applyTo(modifications, prismObject); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("OBJECT after:\n{}", prismObject.debugDump()); + } - // Continuing the photo treatment: should we remove the (now obsolete) focus photo? - // We have to test prismObject at this place, because updateFullObject (below) removes photo property from the prismObject. - boolean shouldPhotoBeRemoved = containsFocusPhotoModification && ((FocusType) prismObject.asObjectable()).getJpegPhoto() == null; + // Continuing the photo treatment: should we remove the (now obsolete) focus photo? + // We have to test prismObject at this place, because updateFullObject (below) removes photo property from the prismObject. + boolean shouldPhotoBeRemoved = containsFocusPhotoModification && ((FocusType) prismObject.asObjectable()).getJpegPhoto() == null; - // merge and update object - LOGGER.trace("Translating JAXB to data type."); - RObject rObject = createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); - rObject.setVersion(rObject.getVersion() + 1); + // merge and update object + LOGGER.trace("Translating JAXB to data type."); + RObject rObject = createDataObjectFromJAXB(prismObject, PrismIdentifierGenerator.Operation.MODIFY); + rObject.setVersion(rObject.getVersion() + 1); - updateFullObject(rObject, prismObject); - LOGGER.trace("Starting merge."); - session.merge(rObject); + updateFullObject(rObject, prismObject); + LOGGER.trace("Starting merge."); + session.merge(rObject); - lookupTableHelper.updateLookupTableData(session, rObject, lookupTableModifications); - caseHelper.updateCampaignCases(session, rObject, campaignCaseModifications); + if (closureManager.isEnabled()) { + closureManager.updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext); + } - if (closureManager.isEnabled()) { - closureManager.updateOrgClosure(originalObject, modifications, session, oid, type, OrgClosureManager.Operation.MODIFY, closureContext); + // JpegPhoto cleanup: As said before, if a focus has to have no photo (after modifications are applied), + // we have to remove the photo manually. + if (shouldPhotoBeRemoved) { + Query query = session.createQuery("delete RFocusPhoto where ownerOid = :oid"); + query.setParameter("oid", prismObject.getOid()); + query.executeUpdate(); + LOGGER.trace("Focus photo for {} was deleted", prismObject.getOid()); + } } - // JpegPhoto cleanup: As said before, if a focus has to have no photo (after modifications are applied), - // we have to remove the photo manually. - if (shouldPhotoBeRemoved) { - Query query = session.createQuery("delete RFocusPhoto where ownerOid = :oid"); - query.setParameter("oid", prismObject.getOid()); - query.executeUpdate(); - LOGGER.trace("Focus photo for {} was deleted", prismObject.getOid()); + if (LookupTableType.class.isAssignableFrom(type)) { + lookupTableHelper.updateLookupTableData(session, oid, lookupTableModifications); + } + if (AccessCertificationCampaignType.class.isAssignableFrom(type)) { + caseHelper.updateCampaignCases(session, oid, campaignCaseModifications); } LOGGER.trace("Before commit..."); From 9b34e43a6a3c8faaba0780e9036d297ed580ad01 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 9 Dec 2015 22:59:24 +0100 Subject: [PATCH 088/116] Fixed setting page size for tables related to certification. --- .../admin/certification/PageCertCampaign.java | 5 ++-- .../certification/PageCertCampaigns.java | 5 ++-- .../certification/PageCertDecisions.java | 25 +++---------------- .../certification/PageCertDefinitions.java | 5 ++-- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java index 57837b11f1a..5ab91f90a86 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java @@ -257,11 +257,12 @@ private void initTableLayout(Form mainForm) { provider.setQuery(createCaseQuery()); provider.setCampaignOid(getCampaignOid()); provider.setSort(AccessCertificationCaseType.F_OBJECT_REF.getLocalPart(), SortOrder.ASCENDING); // default sorting + int itemsPerPage = (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_CAMPAIGN_DECISIONS_PANEL); BoxedTablePanel table = new BoxedTablePanel<>(ID_DECISIONS_TABLE, provider, initColumns(), - UserProfileStorage.TableId.PAGE_CERT_CAMPAIGN_DECISIONS_PANEL, - (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_CAMPAIGN_DECISIONS_PANEL)); + UserProfileStorage.TableId.PAGE_CERT_CAMPAIGN_DECISIONS_PANEL, itemsPerPage); table.setShowPaging(true); table.setOutputMarkupId(true); + table.setItemsPerPage(itemsPerPage); mainForm.add(table); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java index bef3efea613..0d66cb2a1dd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaigns.java @@ -262,12 +262,13 @@ public void yesPerformed(AjaxRequestTarget target) { }); CertCampaignListItemDtoProvider provider = createProvider(); + int itemsPerPage = (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_CAMPAIGNS_PANEL); BoxedTablePanel table = new BoxedTablePanel<>( ID_CAMPAIGNS_TABLE, provider, initColumns(), - UserProfileStorage.TableId.PAGE_CERT_CAMPAIGNS_PANEL, - (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_CAMPAIGNS_PANEL)); + UserProfileStorage.TableId.PAGE_CERT_CAMPAIGNS_PANEL, itemsPerPage); table.setShowPaging(true); table.setOutputMarkupId(true); + table.setItemsPerPage(itemsPerPage); mainForm.add(table); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java index c7b0eedc1f9..3c6cb675360 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java @@ -116,26 +116,6 @@ private CertDecisionDtoProvider createProvider() { private ObjectQuery createCaseQuery() { ObjectQuery query = new ObjectQuery(); - - // implemented as a special notDecidedOnly parameter -// Boolean notDecidedOnly = showNotDecidedOnlyModel.getObject(); -// if (Boolean.TRUE.equals(notDecidedOnly)) { -// -// PrismContainerDefinition pcd = getPrismContext().getSchemaRegistry().findContainerDefinitionByCompileTimeClass(AccessCertificationCaseType.class); -// -// ObjectFilter filter; -// try { -// filter = OrFilter.createOr( -// EqualFilter.createEqual(new ItemPath(AccessCertificationCaseType.F_DECISION, -// AccessCertificationDecisionType.F_RESPONSE), pcd, null), -// EqualFilter.createEqual(new ItemPath(AccessCertificationCaseType.F_DECISION, -// AccessCertificationDecisionType.F_RESPONSE), pcd, AccessCertificationResponseType.NO_RESPONSE)); -// } catch (SchemaException e) { -// throw new SystemException("Unexpected schema exception: " + e.getMessage(), e); -// } -// -// query.setFilter(filter); -// } return query; } @@ -160,9 +140,9 @@ private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); CertDecisionDtoProvider provider = createProvider(); + int itemsPerPage = (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_DECISIONS_PANEL); BoxedTablePanel table = new BoxedTablePanel(ID_DECISIONS_TABLE, provider, initColumns(), - UserProfileStorage.TableId.PAGE_CERT_DECISIONS_PANEL, - (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_DECISIONS_PANEL)) { + UserProfileStorage.TableId.PAGE_CERT_DECISIONS_PANEL, itemsPerPage) { @Override protected WebMarkupContainer createHeader(String headerId) { @@ -171,6 +151,7 @@ protected WebMarkupContainer createHeader(String headerId) { }; table.setShowPaging(true); table.setOutputMarkupId(true); + table.setItemsPerPage(itemsPerPage); // really don't know why this is necessary, as e.g. in PageRoles the size setting works without it mainForm.add(table); // adding this on outer feedback panel prevents displaying the error messages diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java index 996e8131c2e..333779c4ad8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java @@ -120,11 +120,12 @@ public void yesPerformed(AjaxRequestTarget target) { deleteDefinitionPerformed(target, singleDelete); } }); + int itemsPerPage = (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_DEFINITIONS_PANEL); BoxedTablePanel table = new BoxedTablePanel<>(ID_DEFINITIONS_TABLE, provider, initColumns(), - UserProfileStorage.TableId.PAGE_CERT_DEFINITIONS_PANEL, - (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CERT_DEFINITIONS_PANEL)); + UserProfileStorage.TableId.PAGE_CERT_DEFINITIONS_PANEL, itemsPerPage); table.setShowPaging(false); table.setOutputMarkupId(true); + table.setItemsPerPage(itemsPerPage); mainForm.add(table); } From 2562941584a9207ae9e16ddef4029f179f939d2f Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 9 Dec 2015 23:23:15 +0100 Subject: [PATCH 089/116] Small enhancement of cert tests. --- .../test/AbstractCertificationTest.java | 5 ++- .../test/BasicCertificationTest.java | 32 +++++++-------- .../test/RoleInducementCertificationTest.java | 41 +++++++------------ 3 files changed, 35 insertions(+), 43 deletions(-) diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java index 31c5075c567..17f8c680af0 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/AbstractCertificationTest.java @@ -213,12 +213,15 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti } - protected AccessCertificationCaseType checkCase(Collection caseList, String subjectOid, String targetOid, FocusType focus) { + protected AccessCertificationCaseType checkCase(Collection caseList, String subjectOid, String targetOid, FocusType focus, String campaignOid) { AccessCertificationCaseType ccase = findCase(caseList, subjectOid, targetOid); assertNotNull("Certification case for " + subjectOid + ":" + targetOid + " was not found", ccase); assertNotNull("reviewRequestedTimestamp", ccase.getReviewRequestedTimestamp()); assertNotNull("deadline", ccase.getReviewDeadline()); assertNull("remediedTimestamp", ccase.getRemediedTimestamp()); + if (campaignOid != null) { + assertEquals("incorrect campaign OID in case", campaignOid, ccase.getCampaignRef().getOid()); + } return checkSpecificCase(ccase, focus); } diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java index 54dd34299d0..872933ae3ce 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java @@ -170,7 +170,7 @@ public void test020OpenFirstStage() throws Exception { assertEquals("wrong stage #", 1, stage.getNumber()); assertApproximateTime("stage 1 start", new Date(), stage.getStart()); assertNotNull("stage 1 end", stage.getEnd()); // too lazy to compute exact datetime - checkAllCases(campaign.getCase()); + checkAllCases(campaign.getCase(), campaignOid); } protected void assertDefinitionAndOwner(AccessCertificationCampaignType campaign, PrismObject certificationDefinition) { @@ -199,7 +199,7 @@ public void test030SearchAllCases() throws Exception { TestUtil.assertSuccess(result); display("caseList", caseList); - checkAllCases(caseList); + checkAllCases(caseList, campaignOid); } @Test @@ -234,8 +234,8 @@ public void test040SearchCasesFilteredSortedPaged() throws Exception { display("caseList", caseList); assertEquals("Wrong number of certification cases", 2, caseList.size()); - checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_COO_OID, userAdministrator); - checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_CEO_OID, userAdministrator); + checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_COO_OID, userAdministrator, campaignOid); + checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_CEO_OID, userAdministrator, campaignOid); assertEquals("Wrong target OID in case #0", ROLE_COO_OID, caseList.get(0).getTargetRef().getOid()); assertEquals("Wrong target OID in case #1", ROLE_CEO_OID, caseList.get(1).getTargetRef().getOid()); } @@ -261,7 +261,7 @@ public void test050SearchDecisions() throws Exception { display("caseList", caseList); assertEquals("Wrong number of certification cases", 6, caseList.size()); - checkAllCases(caseList); + checkAllCases(caseList, campaignOid); } @Test @@ -294,7 +294,7 @@ public void test100RecordDecision() throws Exception { caseList = certificationManager.searchCases(campaignOid, null, null, task, result); display("caseList", caseList); - checkAllCases(caseList); + checkAllCases(caseList, campaignOid); superuserCase = findCase(caseList, USER_ADMINISTRATOR_OID, ROLE_SUPERUSER_OID); assertEquals("changed case ID", Long.valueOf(id), superuserCase.asPrismContainerValue().getId()); @@ -338,7 +338,7 @@ public void test105RecordAcceptJackCeo() throws Exception { caseList = certificationManager.searchCases(campaignOid, null, null, task, result); display("caseList", caseList); - checkAllCases(caseList); + checkAllCases(caseList, campaignOid); ceoCase = findCase(caseList, USER_JACK_OID, ROLE_CEO_OID); assertEquals("changed case ID", Long.valueOf(id), ceoCase.asPrismContainerValue().getId()); @@ -382,7 +382,7 @@ public void test110RecordRevokeJackCeo() throws Exception { caseList = certificationManager.searchCases(campaignOid, null, null, task, result); display("caseList", caseList); - checkAllCases(caseList); + checkAllCases(caseList, campaignOid); ceoCase = findCase(caseList, USER_JACK_OID, ROLE_CEO_OID); display("CEO case", ceoCase.asPrismContainerValue()); @@ -398,14 +398,14 @@ public void test110RecordRevokeJackCeo() throws Exception { //assertEquals("wrong enabled", true, ceoCase.isEnabled()); } - protected void checkAllCases(Collection caseList) { + protected void checkAllCases(Collection caseList, String campaignOid) { assertEquals("Wrong number of certification cases", 6, caseList.size()); - checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_SUPERUSER_OID, userAdministrator); - checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_COO_OID, userAdministrator); - checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_CEO_OID, userAdministrator); - checkCase(caseList, USER_ADMINISTRATOR_OID, ORG_EROOT_OID, userAdministrator); - checkCase(caseList, USER_JACK_OID, ROLE_CEO_OID, userJack); - checkCase(caseList, USER_JACK_OID, ORG_EROOT_OID, userJack); + checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_SUPERUSER_OID, userAdministrator, campaignOid); + checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_COO_OID, userAdministrator, campaignOid); + checkCase(caseList, USER_ADMINISTRATOR_OID, ROLE_CEO_OID, userAdministrator, campaignOid); + checkCase(caseList, USER_ADMINISTRATOR_OID, ORG_EROOT_OID, userAdministrator, campaignOid); + checkCase(caseList, USER_JACK_OID, ROLE_CEO_OID, userJack, campaignOid); + checkCase(caseList, USER_JACK_OID, ORG_EROOT_OID, userJack, campaignOid); } @Test @@ -437,7 +437,7 @@ public void test150CloseFirstStage() throws Exception { assertEquals("wrong stage #", 1, stage.getNumber()); assertApproximateTime("stage 1 start", new Date(), stage.getStart()); //assertApproximateTime("stage 1 end", new Date(), stage.getStart()); // TODO when implemented - checkAllCases(campaign.getCase()); + checkAllCases(campaign.getCase(), campaignOid); } @Test diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java index 2d136181cb2..1e676ad305a 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java @@ -26,21 +26,12 @@ import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCasesStatisticsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationStageType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import org.springframework.test.annotation.DirtiesContext; @@ -51,9 +42,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Date; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.CLOSED; @@ -205,7 +194,7 @@ public void test020OpenFirstStage() throws Exception { assertEquals("wrong stage #", 1, stage.getNumber()); assertApproximateTime("stage 1 start", new Date(), stage.getStart()); assertNotNull("stage 1 end", stage.getEnd()); // too lazy to compute exact datetime - checkAllCases(campaign.getCase()); + checkAllCases(campaign.getCase(), campaignOid); } protected void assertDefinitionAndOwner(AccessCertificationCampaignType campaign, PrismObject certificationDefinition) { @@ -264,8 +253,8 @@ public void test030SearchAllCases() throws Exception { TestUtil.assertSuccess(result); display("caseList", caseList); - checkAllCases(caseList); - AccessCertificationCaseType _case = checkCase(caseList, ROLE_SUPERUSER_OID, RESOURCE_DUMMY_OID, roleSuperuser); + checkAllCases(caseList, campaignOid); + AccessCertificationCaseType _case = checkCase(caseList, ROLE_SUPERUSER_OID, RESOURCE_DUMMY_OID, roleSuperuser, campaignOid); assertEquals("Unexpected number of reviewers in superuser case", 0, _case.getReviewerRef().size()); } @@ -297,9 +286,9 @@ public void test050SearchDecisionsAdministrator() throws Exception { display("caseList", caseList); assertEquals("Wrong number of certification cases", 3, caseList.size()); - checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_OID, roleCoo); - checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, roleCoo); - checkCase(caseList, ROLE_COO_OID, ROLE_SUPERUSER_OID, roleCoo); + checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_OID, roleCoo, campaignOid); + checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, roleCoo, campaignOid); + checkCase(caseList, ROLE_COO_OID, ROLE_SUPERUSER_OID, roleCoo, campaignOid); } @Test @@ -328,7 +317,7 @@ public void test051SearchDecisionsElaine() throws Exception { display("caseList", caseList); assertEquals("Wrong number of certification cases", 1, caseList.size()); - checkCase(caseList, ROLE_CEO_OID, RESOURCE_DUMMY_OID, roleCeo); + checkCase(caseList, ROLE_CEO_OID, RESOURCE_DUMMY_OID, roleCeo, campaignOid); } @Test @@ -398,7 +387,7 @@ public void test100RecordDecisions() throws Exception { caseList = certificationManager.searchCases(campaignOid, null, null, task, result); display("caseList", caseList); - checkAllCases(caseList); + checkAllCases(caseList, campaignOid); ceoDummyCase = findCase(caseList, ROLE_CEO_OID, RESOURCE_DUMMY_OID); cooDummyCase = findCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_OID); @@ -411,13 +400,13 @@ public void test100RecordDecisions() throws Exception { assertDecision(cooSuperuserCase, NOT_DECIDED, "I'm so procrastinative...", 1, USER_ADMINISTRATOR_OID, ACCEPT, true); } - protected void checkAllCases(Collection caseList) { + protected void checkAllCases(Collection caseList, String campaignOid) { assertEquals("Wrong number of certification cases", 5, caseList.size()); - checkCase(caseList, ROLE_CEO_OID, RESOURCE_DUMMY_OID, roleCeo); - checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_OID, roleCoo); - checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, roleCoo); - checkCase(caseList, ROLE_COO_OID, ROLE_SUPERUSER_OID, roleCoo); - checkCase(caseList, ROLE_SUPERUSER_OID, RESOURCE_DUMMY_OID, roleSuperuser); + checkCase(caseList, ROLE_CEO_OID, RESOURCE_DUMMY_OID, roleCeo, campaignOid); + checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_OID, roleCoo, campaignOid); + checkCase(caseList, ROLE_COO_OID, RESOURCE_DUMMY_BLACK_OID, roleCoo, campaignOid); + checkCase(caseList, ROLE_COO_OID, ROLE_SUPERUSER_OID, roleCoo, campaignOid); + checkCase(caseList, ROLE_SUPERUSER_OID, RESOURCE_DUMMY_OID, roleSuperuser, campaignOid); } @Test @@ -480,7 +469,7 @@ public void test150CloseFirstStage() throws Exception { assertEquals("wrong stage #", 1, stage.getNumber()); assertApproximateTime("stage 1 start", new Date(), stage.getStart()); //assertApproximateTime("stage 1 end", new Date(), stage.getStart()); // TODO when implemented - checkAllCases(campaign.getCase()); + checkAllCases(campaign.getCase(), campaignOid); List caseList = certificationManager.searchCases(campaignOid, null, null, task, result); AccessCertificationCaseType ceoDummyCase = findCase(caseList, ROLE_CEO_OID, RESOURCE_DUMMY_OID); From 2313b7a95f1845a0d48c9aaf084cf8d4b724c750 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Dec 2015 00:17:44 +0100 Subject: [PATCH 090/116] Fixed NPE and index problems found in last moment... --- .../midpoint/notifications/impl/formatters/TextFormatter.java | 3 +++ .../midpoint/repo/sql/data/audit/RAuditEventRecord.java | 2 +- .../evolveum/midpoint/repo/sql/data/common/RAbstractRole.java | 2 +- .../com/evolveum/midpoint/repo/sql/data/common/RUser.java | 4 ++-- .../sql/data/common/container/RAccessCertificationCase.java | 4 ++-- .../midpoint/repo/sql/data/common/container/RAssignment.java | 1 + 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java index 690925cd1ee..2ddd7e92d86 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java @@ -451,6 +451,9 @@ private String getItemLabel(Item item) { } private List filterAndOrderItems(List items, List hiddenPaths, boolean showOperationalAttributes) { + if (items == null) { + return new ArrayList<>(); + } List toBeDisplayed = new ArrayList(items.size()); for (Item item : items) { if (item.getDefinition() != null) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java index d87d75a834b..d088a8ac65f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java @@ -51,7 +51,7 @@ */ @Entity @Table(name = RAuditEventRecord.TABLE_NAME, indexes = { - @Index(name = "iTimestampValue", columnList = RAuditEventRecord.COLUMN_TIMESTAMP)}) + @Index(name = "iTimestampValue", columnList = RAuditEventRecord.COLUMN_TIMESTAMP)}) // TODO correct index name public class RAuditEventRecord implements Serializable { public static final String TABLE_NAME = "m_audit_event"; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java index 8a010bc8de1..acd236af14b 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAbstractRole.java @@ -57,7 +57,7 @@ @Entity @ForeignKey(name = "fk_abstract_role") @org.hibernate.annotations.Table(appliesTo = "m_abstract_role", - indexes = {@Index(name = "iRequestable", columnNames = "requestable")}) + indexes = {@Index(name = "iRequestable", columnNames = "requestable")}) // TODO correct index name public abstract class RAbstractRole extends RFocus { private Set exclusion; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RUser.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RUser.java index e2945b18d04..83b865fe44d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RUser.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RUser.java @@ -43,7 +43,7 @@ @Entity @Table(uniqueConstraints = @UniqueConstraint(name="uc_user_name", columnNames = {"name_norm"})) @org.hibernate.annotations.Table(appliesTo = "m_user", - indexes = {@Index(name = "iFullName", columnNames = "fullName_orig"), + indexes = {@Index(name = "iFullName", columnNames = "fullName_orig"), // TODO correct indices names @Index(name = "iFamilyName", columnNames = "familyName_orig"), @Index(name = "iGivenName", columnNames = "givenName_orig"), @Index(name = "iLocality", columnNames = "locality_orig")}) @@ -141,7 +141,7 @@ public RPolyString getLocalityUser() { return localityUser; } - @Index(name = "iEmployeeNumber") + @Index(name = "iEmployeeNumber") // TODO correct index name public String getEmployeeNumber() { return employeeNumber; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 7a753076f50..12585b26786 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -71,8 +71,8 @@ @Entity @IdClass(RContainerId.class) @Table(name = "m_acc_cert_case", indexes = { - @Index(name = "iObjectRefTargetOid", columnList = "objectRef_targetOid"), - @Index(name = "iTargetRefTargetOid", columnList = "targetRef_targetOid") + @Index(name = "iCaseObjectRefTargetOid", columnList = "objectRef_targetOid"), + @Index(name = "iCaseTargetRefTargetOid", columnList = "targetRef_targetOid") }) public class RAccessCertificationCase implements Container { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java index 8434e9ac4c5..a705727ba42 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAssignment.java @@ -78,6 +78,7 @@ } ) @IdClass(RContainerId.class) +// TODO prefix last 4 index names with "iAssignment" (some day) @Table(name = "m_assignment", indexes = { @Index(name = "iAssignmentAdministrative", columnList = "administrativeStatus"), @Index(name = "iAssignmentEffective", columnList = "effectiveStatus"), From 2d8e355810d06e0191a6130e255267af8d66ec22 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Dec 2015 11:08:01 +0100 Subject: [PATCH 091/116] Added tenantRef, orgRef and activation information to certification case. --- .../xml/ns/public/common/common-3.xsd | 31 +++++++ .../api/CertificationManager.java | 13 ++- .../impl/AccCertQueryHelper.java | 4 + .../DirectAssignmentCertificationHandler.java | 3 + .../test/AbstractCertificationTest.java | 14 +++ .../test/BasicCertificationTest.java | 90 ++++++++++++++++++- .../src/test/resources/common/user-jack.xml | 9 +- .../container/RAccessCertificationCase.java | 49 +++++++++- .../sql/helpers/CertificationCaseHelper.java | 9 +- 9 files changed, 204 insertions(+), 18 deletions(-) diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 1058e2386ab..62abc99c14a 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -12696,6 +12696,37 @@ + + + + For parameterized certification items (e.g. assignments): a tenant parameter, if applicable. + See discussion on tenantRef in AssignmentType. + + + tns:OrgType + + + + + + + For parameterized certification items (e.g. assignments): an org parameter, if applicable. + See discussion on orgRef in AssignmentType. + + + tns:OrgType + + + + + + + If the target is assigned with activation information (e.g. validFrom/validTo/administrativeStatus) + here is the information copied. Note that other activation information (e.g. effectiveStatus) are + _not_ updated here and probably should be ignored. + + + - + + + enabled + + + enabled diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index 12585b26786..ef4ae123281 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.repo.sql.data.common.RAccessCertificationCampaign; import com.evolveum.midpoint.repo.sql.data.common.RObject; +import com.evolveum.midpoint.repo.sql.data.common.embedded.RActivation; import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.enums.RAccessCertificationResponse; import com.evolveum.midpoint.repo.sql.data.common.id.RContainerId; @@ -30,6 +31,7 @@ import com.evolveum.midpoint.repo.sql.query.definition.OwnerIdGetter; import com.evolveum.midpoint.repo.sql.query2.definition.IdQueryProperty; import com.evolveum.midpoint.repo.sql.query2.definition.NotQueryable; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -72,7 +74,9 @@ @IdClass(RContainerId.class) @Table(name = "m_acc_cert_case", indexes = { @Index(name = "iCaseObjectRefTargetOid", columnList = "objectRef_targetOid"), - @Index(name = "iCaseTargetRefTargetOid", columnList = "targetRef_targetOid") + @Index(name = "iCaseTargetRefTargetOid", columnList = "targetRef_targetOid"), + @Index(name = "iCaseTenantRefTargetOid", columnList = "tenantRef_targetOid"), + @Index(name = "iCaseOrgRefTargetOid", columnList = "orgRef_targetOid") }) public class RAccessCertificationCase implements Container { @@ -91,6 +95,9 @@ public class RAccessCertificationCase implements Container { private Set reviewerRef; private REmbeddedReference objectRef; private REmbeddedReference targetRef; + private REmbeddedReference tenantRef; + private REmbeddedReference orgRef; + private RActivation activation; // we need mainly validFrom + validTo + maybe adminStatus; for simplicity we added whole ActivationType here private XMLGregorianCalendar reviewRequestedTimestamp; private XMLGregorianCalendar reviewDeadline; @@ -159,6 +166,21 @@ public REmbeddedReference getObjectRef() { return objectRef; } + @Embedded + public REmbeddedReference getTenantRef() { + return tenantRef; + } + + @Embedded + public REmbeddedReference getOrgRef() { + return orgRef; + } + + @Embedded + public RActivation getActivation() { + return activation; + } + public XMLGregorianCalendar getReviewRequestedTimestamp() { return reviewRequestedTimestamp; } @@ -209,6 +231,18 @@ public void setObjectRef(REmbeddedReference objectRef) { this.objectRef = objectRef; } + public void setTenantRef(REmbeddedReference tenantRef) { + this.tenantRef = tenantRef; + } + + public void setOrgRef(REmbeddedReference orgRef) { + this.orgRef = orgRef; + } + + public void setActivation(RActivation activation) { + this.activation = activation; + } + public void setReviewRequestedTimestamp(XMLGregorianCalendar reviewRequestedTimestamp) { this.reviewRequestedTimestamp = reviewRequestedTimestamp; } @@ -304,24 +338,31 @@ public void setTransient(Boolean trans) { this.trans = trans; } - public static RAccessCertificationCase toRepo(RAccessCertificationCampaign owner, AccessCertificationCaseType case1, PrismContext prismContext) { + public static RAccessCertificationCase toRepo(RAccessCertificationCampaign owner, AccessCertificationCaseType case1, PrismContext prismContext) throws DtoTranslationException { RAccessCertificationCase rCase = toRepo(case1, prismContext); rCase.setOwner(owner); return rCase; } - public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificationCaseType case1, PrismContext prismContext) { + public static RAccessCertificationCase toRepo(String ownerOid, AccessCertificationCaseType case1, PrismContext prismContext) throws DtoTranslationException { RAccessCertificationCase rCase = toRepo(case1, prismContext); rCase.setOwnerOid(ownerOid); return rCase; } - private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, PrismContext prismContext) { + private static RAccessCertificationCase toRepo(AccessCertificationCaseType case1, PrismContext prismContext) throws DtoTranslationException { RAccessCertificationCase rCase = new RAccessCertificationCase(); rCase.setTransient(null); // we don't try to advise hibernate - let it do its work, even if it would cost some SELECTs rCase.setId(RUtil.toInteger(case1.getId())); rCase.setObjectRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getObjectRef(), prismContext)); rCase.setTargetRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getTargetRef(), prismContext)); + rCase.setTenantRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getTenantRef(), prismContext)); + rCase.setOrgRef(RUtil.jaxbRefToEmbeddedRepoRef(case1.getOrgRef(), prismContext)); + if (case1.getActivation() != null) { + RActivation activation = new RActivation(); + RActivation.copyFromJAXB(case1.getActivation(), activation, prismContext); + rCase.setActivation(activation); + } rCase.getReviewerRef().addAll(RCertCaseReference.safeListReferenceToSet( case1.getReviewerRef(), prismContext, rCase, RCReferenceOwner.CASE_REVIEWER)); rCase.setReviewRequestedTimestamp(case1.getReviewRequestedTimestamp()); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java index 93923220d50..ecb3f7b8cd2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/CertificationCaseHelper.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.repo.sql.data.common.RObject; import com.evolveum.midpoint.repo.sql.data.common.container.RAccessCertificationCase; import com.evolveum.midpoint.repo.sql.data.common.container.RCertCaseReference; +import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.GetObjectResult; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; import com.evolveum.midpoint.repo.sql.util.PrismIdentifierGenerator; @@ -94,7 +95,7 @@ public void addCertificationCampaignCases(Session session, RObject object, boole } } - public void addCertificationCampaignCases(Session session, String campaignOid, Collection values, int currentId, List affectedIds) { + public void addCertificationCampaignCases(Session session, String campaignOid, Collection values, int currentId, List affectedIds) throws DtoTranslationException { for (PrismContainerValue value : values) { AccessCertificationCaseType caseType = new AccessCertificationCaseType(); caseType.setupContainerValue(value); @@ -155,7 +156,7 @@ public Collection filterCampaignCase } public void updateCampaignCases(Session session, String campaignOid, - Collection modifications) throws SchemaException, ObjectNotFoundException { + Collection modifications) throws SchemaException, ObjectNotFoundException, DtoTranslationException { if (modifications.isEmpty()) { return; } @@ -166,7 +167,7 @@ public void updateCampaignCases(Session session, String c updateCasesContent(session, campaignOid, modifications, casesAddedOrDeleted); } - protected List addOrDeleteCases(Session session, String campaignOid, Collection modifications) throws SchemaException { + protected List addOrDeleteCases(Session session, String campaignOid, Collection modifications) throws SchemaException, DtoTranslationException { final ItemPath casePath = new ItemPath(AccessCertificationCampaignType.F_CASE); boolean replacePresent = false; List affectedIds = new ArrayList<>(); @@ -220,7 +221,7 @@ protected List addOrDeleteCases(Session session, String campaignOid, Colle return replacePresent ? null : affectedIds; } - private void updateCasesContent(Session session, String campaignOid, Collection modifications, List casesAddedOrDeleted) throws SchemaException, ObjectNotFoundException { + private void updateCasesContent(Session session, String campaignOid, Collection modifications, List casesAddedOrDeleted) throws SchemaException, ObjectNotFoundException, DtoTranslationException { for (ItemDelta delta : modifications) { ItemPath deltaPath = delta.getPath(); if (deltaPath.size() > 1) { From 299fc17649583b67f6a8b6b180bbecfe4620df9a Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Dec 2015 12:33:54 +0100 Subject: [PATCH 092/116] Updated DB scripts. Wrote migration scripts. Fixed names of few indices and 1 column. --- .../3.3/h2/{h2-3.3.sql => h2-3.4.sql} | 110 ++++++++++++++-- .../midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql | 95 ++++++++++++++ .../mysql/{mysql-3.3.sql => mysql-3.4.sql} | 119 ++++++++++++++++-- .../3.3/mysql/mysql-upgrade-3.3-3.4.sql | 105 ++++++++++++++++ .../oracle/{oracle-3.3.sql => oracle-3.4.sql} | 108 ++++++++++++++-- .../3.3/oracle/oracle-upgrade-3.3-3.4.sql | 95 ++++++++++++++ ...{postgresql-3.3.sql => postgresql-3.4.sql} | 116 +++++++++++++++-- .../postgresql/postgresql-upgrade-3.3-3.4.sql | 96 ++++++++++++++ .../{sqlserver-3.3.sql => sqlserver-3.4.sql} | 108 ++++++++++++++-- .../sqlserver/sqlserver-upgrade-3.3-3.4.sql | 96 ++++++++++++++ .../api/CertificationManager.java | 2 +- .../container/RAccessCertificationCase.java | 2 +- .../RAccessCertificationDecision.java | 7 +- .../common/container/RCertCaseReference.java | 4 +- 14 files changed, 1016 insertions(+), 47 deletions(-) rename config/sql/midpoint/3.3/h2/{h2-3.3.sql => h2-3.4.sql} (88%) create mode 100644 config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql rename config/sql/midpoint/3.3/mysql/{mysql-3.3.sql => mysql-3.4.sql} (89%) create mode 100644 config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql rename config/sql/midpoint/3.3/oracle/{oracle-3.3.sql => oracle-3.4.sql} (89%) create mode 100644 config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql rename config/sql/midpoint/3.3/postgresql/{postgresql-3.3.sql => postgresql-3.4.sql} (88%) create mode 100644 config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql rename config/sql/midpoint/3.3/sqlserver/{sqlserver-3.3.sql => sqlserver-3.4.sql} (89%) create mode 100644 config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql diff --git a/config/sql/midpoint/3.3/h2/h2-3.3.sql b/config/sql/midpoint/3.3/h2/h2-3.4.sql similarity index 88% rename from config/sql/midpoint/3.3/h2/h2-3.3.sql rename to config/sql/midpoint/3.3/h2/h2-3.4.sql index 5d1b5b8476c..1443bfa217f 100644 --- a/config/sql/midpoint/3.3/h2/h2-3.3.sql +++ b/config/sql/midpoint/3.3/h2/h2-3.4.sql @@ -6,13 +6,79 @@ CREATE TABLE m_abstract_role ( ); CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR(157), - definitionRef_targetOid VARCHAR(36), - definitionRef_type INTEGER, - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) + definitionRef_relation VARCHAR(157), + definitionRef_targetOid VARCHAR(36), + definitionRef_type INTEGER, + endTimestamp TIMESTAMP, + handlerUri VARCHAR(255), + name_norm VARCHAR(255), + name_orig VARCHAR(255), + ownerRef_relation VARCHAR(157), + ownerRef_targetOid VARCHAR(36), + ownerRef_type INTEGER, + stageNumber INTEGER, + startTimestamp TIMESTAMP, + state INTEGER, + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) +); + +CREATE TABLE m_acc_cert_case ( + id INTEGER NOT NULL, + owner_oid VARCHAR(36) NOT NULL, + administrativeStatus INTEGER, + archiveTimestamp TIMESTAMP, + disableReason VARCHAR(255), + disableTimestamp TIMESTAMP, + effectiveStatus INTEGER, + enableTimestamp TIMESTAMP, + validFrom TIMESTAMP, + validTo TIMESTAMP, + validityChangeTimestamp TIMESTAMP, + validityStatus INTEGER, + currentResponse INTEGER, + currentStageNumber INTEGER, + fullObject BLOB, + objectRef_relation VARCHAR(157), + objectRef_targetOid VARCHAR(36), + objectRef_type INTEGER, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INTEGER, + remediedTimestamp TIMESTAMP, + reviewDeadline TIMESTAMP, + reviewRequestedTimestamp TIMESTAMP, + targetRef_relation VARCHAR(157), + targetRef_targetOid VARCHAR(36), + targetRef_type INTEGER, + tenantRef_relation VARCHAR(157), + tenantRef_targetOid VARCHAR(36), + tenantRef_type INTEGER, + PRIMARY KEY (id, owner_oid) +); + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reference_type INTEGER NOT NULL, + relation VARCHAR(157) NOT NULL, + targetOid VARCHAR(36) NOT NULL, + containerType INTEGER, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +); + +CREATE TABLE m_acc_cert_decision ( + id INTEGER NOT NULL, + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reviewerComment VARCHAR(255), + response INTEGER, + reviewerRef_relation VARCHAR(157), + reviewerRef_targetOid VARCHAR(36), + reviewerRef_type INTEGER, + stageNumber INTEGER NOT NULL, + timestamp TIMESTAMP, + PRIMARY KEY (id, owner_id, owner_owner_oid) ); CREATE TABLE m_acc_cert_definition ( @@ -172,7 +238,7 @@ CREATE TABLE m_audit_delta ( objectName_orig VARCHAR(255), resourceName_norm VARCHAR(255), resourceName_orig VARCHAR(255), - resourceOid varchar(36), + resourceOid VARCHAR(36), status INTEGER, PRIMARY KEY (checksum, record_id) ); @@ -624,6 +690,19 @@ CREATE INDEX iRequestable ON m_abstract_role (requestable); ALTER TABLE m_acc_cert_campaign ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); @@ -776,6 +855,21 @@ ALTER TABLE m_acc_cert_campaign FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT fk_acc_cert_definition FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql new file mode 100644 index 00000000000..50c60a9ec11 --- /dev/null +++ b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql @@ -0,0 +1,95 @@ +ALTER TABLE m_acc_cert_campaign ADD endTimestamp TIMESTAMP; +ALTER TABLE m_acc_cert_campaign ADD handlerUri VARCHAR(255); +ALTER TABLE m_acc_cert_campaign ADD ownerRef_relation VARCHAR(157); +ALTER TABLE m_acc_cert_campaign ADD ownerRef_targetOid VARCHAR(36); +ALTER TABLE m_acc_cert_campaign ADD ownerRef_type INTEGER; +ALTER TABLE m_acc_cert_campaign ADD stageNumber INTEGER; +ALTER TABLE m_acc_cert_campaign ADD startTimestamp TIMESTAMP; +ALTER TABLE m_acc_cert_campaign ADD state INTEGER; + +CREATE TABLE m_acc_cert_case ( + id INTEGER NOT NULL, + owner_oid VARCHAR(36) NOT NULL, + administrativeStatus INTEGER, + archiveTimestamp TIMESTAMP, + disableReason VARCHAR(255), + disableTimestamp TIMESTAMP, + effectiveStatus INTEGER, + enableTimestamp TIMESTAMP, + validFrom TIMESTAMP, + validTo TIMESTAMP, + validityChangeTimestamp TIMESTAMP, + validityStatus INTEGER, + currentResponse INTEGER, + currentStageNumber INTEGER, + fullObject BLOB, + objectRef_relation VARCHAR(157), + objectRef_targetOid VARCHAR(36), + objectRef_type INTEGER, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INTEGER, + remediedTimestamp TIMESTAMP, + reviewDeadline TIMESTAMP, + reviewRequestedTimestamp TIMESTAMP, + targetRef_relation VARCHAR(157), + targetRef_targetOid VARCHAR(36), + targetRef_type INTEGER, + tenantRef_relation VARCHAR(157), + tenantRef_targetOid VARCHAR(36), + tenantRef_type INTEGER, + PRIMARY KEY (id, owner_oid) +); + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reference_type INTEGER NOT NULL, + relation VARCHAR(157) NOT NULL, + targetOid VARCHAR(36) NOT NULL, + containerType INTEGER, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +); + +CREATE TABLE m_acc_cert_decision ( + id INTEGER NOT NULL, + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reviewerComment VARCHAR(255), + response INTEGER, + reviewerRef_relation VARCHAR(157), + reviewerRef_targetOid VARCHAR(36), + reviewerRef_type INTEGER, + stageNumber INTEGER NOT NULL, + timestamp TIMESTAMP, + PRIMARY KEY (id, owner_id, owner_owner_oid) +); + +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + diff --git a/config/sql/midpoint/3.3/mysql/mysql-3.3.sql b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql similarity index 89% rename from config/sql/midpoint/3.3/mysql/mysql-3.3.sql rename to config/sql/midpoint/3.3/mysql/mysql-3.4.sql index 58fc96a0e32..1a5761fe28b 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-3.3.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql @@ -22,17 +22,92 @@ CREATE TABLE m_abstract_role ( ENGINE = InnoDB; CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR(157), - definitionRef_targetOid VARCHAR(36), - definitionRef_type INTEGER, - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) + definitionRef_relation VARCHAR(157), + definitionRef_targetOid VARCHAR(36), + definitionRef_type INTEGER, + endTimestamp DATETIME(6), + handlerUri VARCHAR(255), + name_norm VARCHAR(255), + name_orig VARCHAR(255), + ownerRef_relation VARCHAR(157), + ownerRef_targetOid VARCHAR(36), + ownerRef_type INTEGER, + stageNumber INTEGER, + startTimestamp DATETIME(6), + state INTEGER, + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) ) DEFAULT CHARACTER SET utf8 COLLATE utf8_bin - ENGINE=InnoDB; + ENGINE = InnoDB; + +CREATE TABLE m_acc_cert_case ( + id INTEGER NOT NULL, + owner_oid VARCHAR(36) NOT NULL, + administrativeStatus INTEGER, + archiveTimestamp DATETIME(6), + disableReason VARCHAR(255), + disableTimestamp DATETIME(6), + effectiveStatus INTEGER, + enableTimestamp DATETIME(6), + validFrom DATETIME(6), + validTo DATETIME(6), + validityChangeTimestamp DATETIME(6), + validityStatus INTEGER, + currentResponse INTEGER, + currentStageNumber INTEGER, + fullObject LONGBLOB, + objectRef_relation VARCHAR(157), + objectRef_targetOid VARCHAR(36), + objectRef_type INTEGER, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INTEGER, + remediedTimestamp DATETIME(6), + reviewDeadline DATETIME(6), + reviewRequestedTimestamp DATETIME(6), + targetRef_relation VARCHAR(157), + targetRef_targetOid VARCHAR(36), + targetRef_type INTEGER, + tenantRef_relation VARCHAR(157), + tenantRef_targetOid VARCHAR(36), + tenantRef_type INTEGER, + PRIMARY KEY (id, owner_oid) +) + DEFAULT CHARACTER SET utf8 + COLLATE utf8_bin + ENGINE = InnoDB; + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reference_type INTEGER NOT NULL, + relation VARCHAR(157) NOT NULL, + targetOid VARCHAR(36) NOT NULL, + containerType INTEGER, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +) + DEFAULT CHARACTER SET utf8 + COLLATE utf8_bin + ENGINE = InnoDB; + +CREATE TABLE m_acc_cert_decision ( + id INTEGER NOT NULL, + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reviewerComment VARCHAR(255), + response INTEGER, + reviewerRef_relation VARCHAR(157), + reviewerRef_targetOid VARCHAR(36), + reviewerRef_type INTEGER, + stageNumber INTEGER NOT NULL, + timestamp DATETIME(6), + PRIMARY KEY (id, owner_id, owner_owner_oid) +) + DEFAULT CHARACTER SET utf8 + COLLATE utf8_bin + ENGINE = InnoDB; CREATE TABLE m_acc_cert_definition ( name_norm VARCHAR(255), @@ -793,6 +868,19 @@ CREATE INDEX iRequestable ON m_abstract_role (requestable); ALTER TABLE m_acc_cert_campaign ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); @@ -947,6 +1035,21 @@ ALTER TABLE m_acc_cert_campaign FOREIGN KEY (oid) REFERENCES m_object (oid); +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object (oid); + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case (id, owner_oid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case (id, owner_oid); + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT fk_acc_cert_definition FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql new file mode 100644 index 00000000000..2d5b4081211 --- /dev/null +++ b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql @@ -0,0 +1,105 @@ +ALTER TABLE m_acc_cert_campaign +ADD endTimestamp DATETIME(6), +ADD handlerUri VARCHAR(255), +ADD ownerRef_relation VARCHAR(157), +ADD ownerRef_targetOid VARCHAR(36), +ADD ownerRef_type INTEGER, +ADD stageNumber INTEGER, +ADD startTimestamp DATETIME(6), +ADD state INTEGER; + +CREATE TABLE m_acc_cert_case ( + id INTEGER NOT NULL, + owner_oid VARCHAR(36) NOT NULL, + administrativeStatus INTEGER, + archiveTimestamp DATETIME(6), + disableReason VARCHAR(255), + disableTimestamp DATETIME(6), + effectiveStatus INTEGER, + enableTimestamp DATETIME(6), + validFrom DATETIME(6), + validTo DATETIME(6), + validityChangeTimestamp DATETIME(6), + validityStatus INTEGER, + currentResponse INTEGER, + currentStageNumber INTEGER, + fullObject LONGBLOB, + objectRef_relation VARCHAR(157), + objectRef_targetOid VARCHAR(36), + objectRef_type INTEGER, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INTEGER, + remediedTimestamp DATETIME(6), + reviewDeadline DATETIME(6), + reviewRequestedTimestamp DATETIME(6), + targetRef_relation VARCHAR(157), + targetRef_targetOid VARCHAR(36), + targetRef_type INTEGER, + tenantRef_relation VARCHAR(157), + tenantRef_targetOid VARCHAR(36), + tenantRef_type INTEGER, + PRIMARY KEY (id, owner_oid) +) + DEFAULT CHARACTER SET utf8 + COLLATE utf8_bin + ENGINE = InnoDB; + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reference_type INTEGER NOT NULL, + relation VARCHAR(157) NOT NULL, + targetOid VARCHAR(36) NOT NULL, + containerType INTEGER, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +) + DEFAULT CHARACTER SET utf8 + COLLATE utf8_bin + ENGINE = InnoDB; + +CREATE TABLE m_acc_cert_decision ( + id INTEGER NOT NULL, + owner_id INTEGER NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reviewerComment VARCHAR(255), + response INTEGER, + reviewerRef_relation VARCHAR(157), + reviewerRef_targetOid VARCHAR(36), + reviewerRef_type INTEGER, + stageNumber INTEGER NOT NULL, + timestamp DATETIME(6), + PRIMARY KEY (id, owner_id, owner_owner_oid) +) + DEFAULT CHARACTER SET utf8 + COLLATE utf8_bin + ENGINE = InnoDB; + +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object (oid); + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case (id, owner_oid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case (id, owner_oid); + diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.3.sql b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql similarity index 89% rename from config/sql/midpoint/3.3/oracle/oracle-3.3.sql rename to config/sql/midpoint/3.3/oracle/oracle-3.4.sql index 67435c2acfb..296a44181ae 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.3.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql @@ -9,13 +9,79 @@ CREATE TABLE m_abstract_role ( ) INITRANS 30; CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR2(157 CHAR), - definitionRef_targetOid VARCHAR2(36 CHAR), - definitionRef_type NUMBER(10,0), - name_norm VARCHAR2(255 CHAR), - name_orig VARCHAR2(255 CHAR), - oid VARCHAR2(36 CHAR) NOT NULL, - PRIMARY KEY (oid) + definitionRef_relation VARCHAR2(157 CHAR), + definitionRef_targetOid VARCHAR2(36 CHAR), + definitionRef_type NUMBER(10, 0), + endTimestamp TIMESTAMP, + handlerUri VARCHAR2(255 CHAR), + name_norm VARCHAR2(255 CHAR), + name_orig VARCHAR2(255 CHAR), + ownerRef_relation VARCHAR2(157 CHAR), + ownerRef_targetOid VARCHAR2(36 CHAR), + ownerRef_type NUMBER(10, 0), + stageNumber NUMBER(10, 0), + startTimestamp TIMESTAMP, + state NUMBER(10, 0), + oid VARCHAR2(36 CHAR) NOT NULL, + PRIMARY KEY (oid) +) INITRANS 30; + +CREATE TABLE m_acc_cert_case ( + id NUMBER(10, 0) NOT NULL, + owner_oid VARCHAR2(36 CHAR) NOT NULL, + administrativeStatus NUMBER(10, 0), + archiveTimestamp TIMESTAMP, + disableReason VARCHAR2(255 CHAR), + disableTimestamp TIMESTAMP, + effectiveStatus NUMBER(10, 0), + enableTimestamp TIMESTAMP, + validFrom TIMESTAMP, + validTo TIMESTAMP, + validityChangeTimestamp TIMESTAMP, + validityStatus NUMBER(10, 0), + currentResponse NUMBER(10, 0), + currentStageNumber NUMBER(10, 0), + fullObject BLOB, + objectRef_relation VARCHAR2(157 CHAR), + objectRef_targetOid VARCHAR2(36 CHAR), + objectRef_type NUMBER(10, 0), + orgRef_relation VARCHAR2(157 CHAR), + orgRef_targetOid VARCHAR2(36 CHAR), + orgRef_type NUMBER(10, 0), + remediedTimestamp TIMESTAMP, + reviewDeadline TIMESTAMP, + reviewRequestedTimestamp TIMESTAMP, + targetRef_relation VARCHAR2(157 CHAR), + targetRef_targetOid VARCHAR2(36 CHAR), + targetRef_type NUMBER(10, 0), + tenantRef_relation VARCHAR2(157 CHAR), + tenantRef_targetOid VARCHAR2(36 CHAR), + tenantRef_type NUMBER(10, 0), + PRIMARY KEY (id, owner_oid) +) INITRANS 30; + +CREATE TABLE m_acc_cert_case_reference ( + owner_id NUMBER(10, 0) NOT NULL, + owner_owner_oid VARCHAR2(36 CHAR) NOT NULL, + reference_type NUMBER(10, 0) NOT NULL, + relation VARCHAR2(157 CHAR) NOT NULL, + targetOid VARCHAR2(36 CHAR) NOT NULL, + containerType NUMBER(10, 0), + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +) INITRANS 30; + +CREATE TABLE m_acc_cert_decision ( + id NUMBER(10, 0) NOT NULL, + owner_id NUMBER(10, 0) NOT NULL, + owner_owner_oid VARCHAR2(36 CHAR) NOT NULL, + reviewerComment VARCHAR2(255 CHAR), + response NUMBER(10, 0), + reviewerRef_relation VARCHAR2(157 CHAR), + reviewerRef_targetOid VARCHAR2(36 CHAR), + reviewerRef_type NUMBER(10, 0), + stageNumber NUMBER(10, 0) NOT NULL, + timestamp TIMESTAMP, + PRIMARY KEY (id, owner_id, owner_owner_oid) ) INITRANS 30; CREATE TABLE m_acc_cert_definition ( @@ -634,6 +700,19 @@ CREATE INDEX iRequestable ON m_abstract_role (requestable) INITRANS 30; ALTER TABLE m_acc_cert_campaign ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm) INITRANS 30; +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid) INITRANS 30; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid) INITRANS 30; + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm) INITRANS 30; @@ -786,6 +865,21 @@ ALTER TABLE m_acc_cert_campaign FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT fk_acc_cert_definition FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql new file mode 100644 index 00000000000..290ffc5e56a --- /dev/null +++ b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql @@ -0,0 +1,95 @@ +ALTER TABLE m_acc_cert_campaign ADD ( +endTimestamp TIMESTAMP, +handlerUri VARCHAR2(255 CHAR), +ownerRef_relation VARCHAR2(157 CHAR), +ownerRef_targetOid VARCHAR2(36 CHAR), +ownerRef_type NUMBER(10, 0), +stageNumber NUMBER(10, 0), +startTimestamp TIMESTAMP, +state NUMBER(10, 0)); + +CREATE TABLE m_acc_cert_case ( + id NUMBER(10, 0) NOT NULL, + owner_oid VARCHAR2(36 CHAR) NOT NULL, + administrativeStatus NUMBER(10, 0), + archiveTimestamp TIMESTAMP, + disableReason VARCHAR2(255 CHAR), + disableTimestamp TIMESTAMP, + effectiveStatus NUMBER(10, 0), + enableTimestamp TIMESTAMP, + validFrom TIMESTAMP, + validTo TIMESTAMP, + validityChangeTimestamp TIMESTAMP, + validityStatus NUMBER(10, 0), + currentResponse NUMBER(10, 0), + currentStageNumber NUMBER(10, 0), + fullObject BLOB, + objectRef_relation VARCHAR2(157 CHAR), + objectRef_targetOid VARCHAR2(36 CHAR), + objectRef_type NUMBER(10, 0), + orgRef_relation VARCHAR2(157 CHAR), + orgRef_targetOid VARCHAR2(36 CHAR), + orgRef_type NUMBER(10, 0), + remediedTimestamp TIMESTAMP, + reviewDeadline TIMESTAMP, + reviewRequestedTimestamp TIMESTAMP, + targetRef_relation VARCHAR2(157 CHAR), + targetRef_targetOid VARCHAR2(36 CHAR), + targetRef_type NUMBER(10, 0), + tenantRef_relation VARCHAR2(157 CHAR), + tenantRef_targetOid VARCHAR2(36 CHAR), + tenantRef_type NUMBER(10, 0), + PRIMARY KEY (id, owner_oid) +) INITRANS 30; + +CREATE TABLE m_acc_cert_case_reference ( + owner_id NUMBER(10, 0) NOT NULL, + owner_owner_oid VARCHAR2(36 CHAR) NOT NULL, + reference_type NUMBER(10, 0) NOT NULL, + relation VARCHAR2(157 CHAR) NOT NULL, + targetOid VARCHAR2(36 CHAR) NOT NULL, + containerType NUMBER(10, 0), + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +) INITRANS 30; + +CREATE TABLE m_acc_cert_decision ( + id NUMBER(10, 0) NOT NULL, + owner_id NUMBER(10, 0) NOT NULL, + owner_owner_oid VARCHAR2(36 CHAR) NOT NULL, + reviewerComment VARCHAR2(255 CHAR), + response NUMBER(10, 0), + reviewerRef_relation VARCHAR2(157 CHAR), + reviewerRef_targetOid VARCHAR2(36 CHAR), + reviewerRef_type NUMBER(10, 0), + stageNumber NUMBER(10, 0) NOT NULL, + timestamp TIMESTAMP, + PRIMARY KEY (id, owner_id, owner_owner_oid) +) INITRANS 30; + +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid) INITRANS 30; + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid) INITRANS 30; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid) INITRANS 30; + +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-3.3.sql b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql similarity index 88% rename from config/sql/midpoint/3.3/postgresql/postgresql-3.3.sql rename to config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql index 3a18ff1c6c0..abae81cd325 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-3.3.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql @@ -6,20 +6,86 @@ CREATE TABLE m_abstract_role ( ); CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation VARCHAR(157), - definitionRef_targetOid VARCHAR(36), - definitionRef_type int4, - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) + definitionRef_relation VARCHAR(157), + definitionRef_targetOid VARCHAR(36), + definitionRef_type INT4, + endTimestamp TIMESTAMP, + handlerUri VARCHAR(255), + name_norm VARCHAR(255), + name_orig VARCHAR(255), + ownerRef_relation VARCHAR(157), + ownerRef_targetOid VARCHAR(36), + ownerRef_type INT4, + stageNumber INT4, + startTimestamp TIMESTAMP, + state INT4, + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) +); + +CREATE TABLE m_acc_cert_case ( + id INT4 NOT NULL, + owner_oid VARCHAR(36) NOT NULL, + administrativeStatus INT4, + archiveTimestamp TIMESTAMP, + disableReason VARCHAR(255), + disableTimestamp TIMESTAMP, + effectiveStatus INT4, + enableTimestamp TIMESTAMP, + validFrom TIMESTAMP, + validTo TIMESTAMP, + validityChangeTimestamp TIMESTAMP, + validityStatus INT4, + currentResponse INT4, + currentStageNumber INT4, + fullObject BYTEA, + objectRef_relation VARCHAR(157), + objectRef_targetOid VARCHAR(36), + objectRef_type INT4, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INT4, + remediedTimestamp TIMESTAMP, + reviewDeadline TIMESTAMP, + reviewRequestedTimestamp TIMESTAMP, + targetRef_relation VARCHAR(157), + targetRef_targetOid VARCHAR(36), + targetRef_type INT4, + tenantRef_relation VARCHAR(157), + tenantRef_targetOid VARCHAR(36), + tenantRef_type INT4, + PRIMARY KEY (id, owner_oid) +); + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INT4 NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reference_type INT4 NOT NULL, + relation VARCHAR(157) NOT NULL, + targetOid VARCHAR(36) NOT NULL, + containerType INT4, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +); + +CREATE TABLE m_acc_cert_decision ( + id INT4 NOT NULL, + owner_id INT4 NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reviewerComment VARCHAR(255), + response INT4, + reviewerRef_relation VARCHAR(157), + reviewerRef_targetOid VARCHAR(36), + reviewerRef_type INT4, + stageNumber INT4 NOT NULL, + timestamp TIMESTAMP, + PRIMARY KEY (id, owner_id, owner_owner_oid) ); CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) + name_norm VARCHAR(255), + name_orig VARCHAR(255), + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) ); CREATE TABLE m_assignment ( @@ -624,6 +690,19 @@ CREATE INDEX iRequestable ON m_abstract_role (requestable); ALTER TABLE m_acc_cert_campaign ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); @@ -776,6 +855,21 @@ ALTER TABLE m_acc_cert_campaign FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT fk_acc_cert_definition FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql new file mode 100644 index 00000000000..b3ae7a03573 --- /dev/null +++ b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql @@ -0,0 +1,96 @@ +ALTER TABLE m_acc_cert_campaign +ADD endTimestamp TIMESTAMP, +ADD handlerUri VARCHAR(255), +ADD ownerRef_relation VARCHAR(157), +ADD ownerRef_targetOid VARCHAR(36), +ADD ownerRef_type INT4, +ADD stageNumber INT4, +ADD startTimestamp TIMESTAMP, +ADD state INT4; + +CREATE TABLE m_acc_cert_case ( + id INT4 NOT NULL, + owner_oid VARCHAR(36) NOT NULL, + administrativeStatus INT4, + archiveTimestamp TIMESTAMP, + disableReason VARCHAR(255), + disableTimestamp TIMESTAMP, + effectiveStatus INT4, + enableTimestamp TIMESTAMP, + validFrom TIMESTAMP, + validTo TIMESTAMP, + validityChangeTimestamp TIMESTAMP, + validityStatus INT4, + currentResponse INT4, + currentStageNumber INT4, + fullObject BYTEA, + objectRef_relation VARCHAR(157), + objectRef_targetOid VARCHAR(36), + objectRef_type INT4, + orgRef_relation VARCHAR(157), + orgRef_targetOid VARCHAR(36), + orgRef_type INT4, + remediedTimestamp TIMESTAMP, + reviewDeadline TIMESTAMP, + reviewRequestedTimestamp TIMESTAMP, + targetRef_relation VARCHAR(157), + targetRef_targetOid VARCHAR(36), + targetRef_type INT4, + tenantRef_relation VARCHAR(157), + tenantRef_targetOid VARCHAR(36), + tenantRef_type INT4, + PRIMARY KEY (id, owner_oid) +); + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INT4 NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reference_type INT4 NOT NULL, + relation VARCHAR(157) NOT NULL, + targetOid VARCHAR(36) NOT NULL, + containerType INT4, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +); + +CREATE TABLE m_acc_cert_decision ( + id INT4 NOT NULL, + owner_id INT4 NOT NULL, + owner_owner_oid VARCHAR(36) NOT NULL, + reviewerComment VARCHAR(255), + response INT4, + reviewerRef_relation VARCHAR(157), + reviewerRef_targetOid VARCHAR(36), + reviewerRef_type INT4, + stageNumber INT4 NOT NULL, + timestamp TIMESTAMP, + PRIMARY KEY (id, owner_id, owner_owner_oid) +); + +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql similarity index 89% rename from config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql rename to config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql index b6afb8095b2..bb8d284589b 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.3.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql @@ -6,13 +6,79 @@ CREATE TABLE m_abstract_role ( ); CREATE TABLE m_acc_cert_campaign ( - definitionRef_relation NVARCHAR(157) COLLATE database_default, - definitionRef_targetOid NVARCHAR(36) COLLATE database_default, - definitionRef_type INT, - name_norm NVARCHAR(255) COLLATE database_default, - name_orig NVARCHAR(255) COLLATE database_default, - oid NVARCHAR(36) COLLATE database_default NOT NULL, - PRIMARY KEY (oid) + definitionRef_relation NVARCHAR(157) COLLATE database_default, + definitionRef_targetOid NVARCHAR(36) COLLATE database_default, + definitionRef_type INT, + endTimestamp DATETIME2, + handlerUri NVARCHAR(255) COLLATE database_default, + name_norm NVARCHAR(255) COLLATE database_default, + name_orig NVARCHAR(255) COLLATE database_default, + ownerRef_relation NVARCHAR(157) COLLATE database_default, + ownerRef_targetOid NVARCHAR(36) COLLATE database_default, + ownerRef_type INT, + stageNumber INT, + startTimestamp DATETIME2, + state INT, + oid NVARCHAR(36) COLLATE database_default NOT NULL, + PRIMARY KEY (oid) +); + +CREATE TABLE m_acc_cert_case ( + id INT NOT NULL, + owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + administrativeStatus INT, + archiveTimestamp DATETIME2, + disableReason NVARCHAR(255) COLLATE database_default, + disableTimestamp DATETIME2, + effectiveStatus INT, + enableTimestamp DATETIME2, + validFrom DATETIME2, + validTo DATETIME2, + validityChangeTimestamp DATETIME2, + validityStatus INT, + currentResponse INT, + currentStageNumber INT, + fullObject VARBINARY(MAX), + objectRef_relation NVARCHAR(157) COLLATE database_default, + objectRef_targetOid NVARCHAR(36) COLLATE database_default, + objectRef_type INT, + orgRef_relation NVARCHAR(157) COLLATE database_default, + orgRef_targetOid NVARCHAR(36) COLLATE database_default, + orgRef_type INT, + remediedTimestamp DATETIME2, + reviewDeadline DATETIME2, + reviewRequestedTimestamp DATETIME2, + targetRef_relation NVARCHAR(157) COLLATE database_default, + targetRef_targetOid NVARCHAR(36) COLLATE database_default, + targetRef_type INT, + tenantRef_relation NVARCHAR(157) COLLATE database_default, + tenantRef_targetOid NVARCHAR(36) COLLATE database_default, + tenantRef_type INT, + PRIMARY KEY (id, owner_oid) +); + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INT NOT NULL, + owner_owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + reference_type INT NOT NULL, + relation NVARCHAR(157) COLLATE database_default NOT NULL, + targetOid NVARCHAR(36) COLLATE database_default NOT NULL, + containerType INT, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +); + +CREATE TABLE m_acc_cert_decision ( + id INT NOT NULL, + owner_id INT NOT NULL, + owner_owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + reviewerComment NVARCHAR(255) COLLATE database_default, + response INT, + reviewerRef_relation NVARCHAR(157) COLLATE database_default, + reviewerRef_targetOid NVARCHAR(36) COLLATE database_default, + reviewerRef_type INT, + stageNumber INT NOT NULL, + timestamp DATETIME2, + PRIMARY KEY (id, owner_id, owner_owner_oid) ); CREATE TABLE m_acc_cert_definition ( @@ -624,6 +690,19 @@ CREATE INDEX iRequestable ON m_abstract_role (requestable); ALTER TABLE m_acc_cert_campaign ADD CONSTRAINT uc_acc_cert_campaign_name UNIQUE (name_norm); +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT uc_acc_cert_definition_name UNIQUE (name_norm); @@ -776,6 +855,21 @@ ALTER TABLE m_acc_cert_campaign FOREIGN KEY (oid) REFERENCES m_object; +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + ALTER TABLE m_acc_cert_definition ADD CONSTRAINT fk_acc_cert_definition FOREIGN KEY (oid) diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql new file mode 100644 index 00000000000..de540e0c2fe --- /dev/null +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql @@ -0,0 +1,96 @@ +ALTER TABLE m_acc_cert_campaign ADD +endTimestamp DATETIME2, +handlerUri NVARCHAR(255) COLLATE database_default, +ownerRef_relation NVARCHAR(157) COLLATE database_default, +ownerRef_targetOid NVARCHAR(36) COLLATE database_default, +ownerRef_type INT, +stageNumber INT, +startTimestamp DATETIME2, +state INT; + +CREATE TABLE m_acc_cert_case ( + id INT NOT NULL, + owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + administrativeStatus INT, + archiveTimestamp DATETIME2, + disableReason NVARCHAR(255) COLLATE database_default, + disableTimestamp DATETIME2, + effectiveStatus INT, + enableTimestamp DATETIME2, + validFrom DATETIME2, + validTo DATETIME2, + validityChangeTimestamp DATETIME2, + validityStatus INT, + currentResponse INT, + currentStageNumber INT, + fullObject VARBINARY(MAX), + objectRef_relation NVARCHAR(157) COLLATE database_default, + objectRef_targetOid NVARCHAR(36) COLLATE database_default, + objectRef_type INT, + orgRef_relation NVARCHAR(157) COLLATE database_default, + orgRef_targetOid NVARCHAR(36) COLLATE database_default, + orgRef_type INT, + remediedTimestamp DATETIME2, + reviewDeadline DATETIME2, + reviewRequestedTimestamp DATETIME2, + targetRef_relation NVARCHAR(157) COLLATE database_default, + targetRef_targetOid NVARCHAR(36) COLLATE database_default, + targetRef_type INT, + tenantRef_relation NVARCHAR(157) COLLATE database_default, + tenantRef_targetOid NVARCHAR(36) COLLATE database_default, + tenantRef_type INT, + PRIMARY KEY (id, owner_oid) +); + +CREATE TABLE m_acc_cert_case_reference ( + owner_id INT NOT NULL, + owner_owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + reference_type INT NOT NULL, + relation NVARCHAR(157) COLLATE database_default NOT NULL, + targetOid NVARCHAR(36) COLLATE database_default NOT NULL, + containerType INT, + PRIMARY KEY (owner_id, owner_owner_oid, reference_type, relation, targetOid) +); + +CREATE TABLE m_acc_cert_decision ( + id INT NOT NULL, + owner_id INT NOT NULL, + owner_owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, + reviewerComment NVARCHAR(255) COLLATE database_default, + response INT, + reviewerRef_relation NVARCHAR(157) COLLATE database_default, + reviewerRef_targetOid NVARCHAR(36) COLLATE database_default, + reviewerRef_type INT, + stageNumber INT NOT NULL, + timestamp DATETIME2, + PRIMARY KEY (id, owner_id, owner_owner_oid) +); + +CREATE INDEX iCaseObjectRefTargetOid ON m_acc_cert_case (objectRef_targetOid); + +CREATE INDEX iCaseTargetRefTargetOid ON m_acc_cert_case (targetRef_targetOid); + +CREATE INDEX iCaseTenantRefTargetOid ON m_acc_cert_case (tenantRef_targetOid); + +CREATE INDEX iCaseOrgRefTargetOid ON m_acc_cert_case (orgRef_targetOid); + +CREATE INDEX iCaseReferenceTargetOid ON m_acc_cert_case_reference (targetOid); + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT uc_case_stage_reviewer UNIQUE (owner_owner_oid, owner_id, stageNumber, reviewerRef_targetOid); + +ALTER TABLE m_acc_cert_case +ADD CONSTRAINT fk_acc_cert_case_owner +FOREIGN KEY (owner_oid) +REFERENCES m_object; + +ALTER TABLE m_acc_cert_case_reference +ADD CONSTRAINT fk_acc_cert_case_reference_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + +ALTER TABLE m_acc_cert_decision +ADD CONSTRAINT fk_acc_cert_decision_owner +FOREIGN KEY (owner_id, owner_owner_oid) +REFERENCES m_acc_cert_case; + diff --git a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java index 537ef913811..913fd65407f 100644 --- a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java +++ b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java @@ -178,7 +178,7 @@ AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType * @param caseQuery Specification of the cases to retrieve. (In future it may contain restrictions on owning campaign(s).) * @param reviewerOid OID of the reviewer whose decisions we want to retrieve. * @param notDecidedOnly If true, only response==(NO_DECISION or null) should be returned. - * Although it can be formulate in Query API terms, this would refer to implementation details - so + * Although it can be formulated in Query API terms, this would refer to implementation details - so * the cleaner way is keep this knowledge inside certification module only. * @param options Options to use (currently supported is RESOLVE_NAMES). * @param task Task in context of which all operations will take place. diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java index ef4ae123281..49769d9b68d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationCase.java @@ -115,7 +115,7 @@ public RAccessCertificationCase(RObject owner) { } @Id - @org.hibernate.annotations.ForeignKey(name = "fk_ac_case_owner") + @org.hibernate.annotations.ForeignKey(name = "fk_acc_cert_case_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) @OwnerGetter(ownerClass = RAccessCertificationCampaign.class) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java index 0160c268121..b78e76c835f 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RAccessCertificationDecision.java @@ -27,9 +27,11 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; -import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.*; import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.Table; import javax.xml.datatype.XMLGregorianCalendar; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType.F_STAGE_NUMBER; @@ -77,7 +79,7 @@ public RAccessCertificationDecision() { } @Id - //@org.hibernate.annotations.ForeignKey(name = "fk_ac_case_owner") + @org.hibernate.annotations.ForeignKey(name = "fk_acc_cert_decision_owner") @ManyToOne(fetch = FetchType.LAZY) @MapsId("owner") @NotQueryable @@ -126,6 +128,7 @@ public RAccessCertificationResponse getResponse() { return response; } + @Column(name = "reviewerComment") // in Oracle, 'comment' is a reserved word public String getComment() { return comment; } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java index 498e4d4e375..26bf3cee30c 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java @@ -56,7 +56,7 @@ @Entity @IdClass(RCObjectReferenceId.class) @Table(name = RCertCaseReference.TABLE, indexes = { - @javax.persistence.Index(name = "iAccCertCaseReferenceTargetOid", columnList = "targetOid") + @javax.persistence.Index(name = "iCaseReferenceTargetOid", columnList = "targetOid") }) public class RCertCaseReference extends RContainerReference { @@ -70,7 +70,7 @@ public class RCertCaseReference extends RContainerReference { // return targetName; // } - @ForeignKey(name = "fk_acc_cert_case_reference") + @ForeignKey(name = "fk_acc_cert_case_reference_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) @NotQueryable From 84e0201899a9c35764600a90bd183bf9b974edc4 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Dec 2015 12:43:16 +0100 Subject: [PATCH 093/116] Attempting to allow null OID to be returned via REST. --- .../midpoint/model/impl/ModelRestService.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java index 50c11d7f9ac..0a6058c0bcd 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java @@ -176,9 +176,16 @@ public Response addObject(@PathParam("type") String type, try { oid = model.addObject(object, modelExecuteOptions, task, parentResult); LOGGER.info("returned oid : {}", oid ); - - URI resourceURI = uriInfo.getAbsolutePathBuilder().path(oid).build(oid); - ResponseBuilder builder = clazz.isAssignableFrom(TaskType.class) ? Response.accepted().location(resourceURI) : Response.created(resourceURI); + + ResponseBuilder builder; + + if (oid != null) { + URI resourceURI = uriInfo.getAbsolutePathBuilder().path(oid).build(oid); + builder = clazz.isAssignableFrom(TaskType.class) ? Response.accepted().location(resourceURI) : Response.created(resourceURI); + } else { + // OID might be null e.g. if the object creation is a subject of workflow approval + builder = Response.accepted(); // TODO is this ok ? + } response = builder.build(); } catch (ObjectAlreadyExistsException e) { From 9c75151f5805097b8323276675e977600204bc04 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Dec 2015 17:27:18 +0100 Subject: [PATCH 094/116] Preliminary implementation of MID-2727 (selective inhibition of response buttons). Added a couple of definition attributes towards MID-2729 (cert scheduling). --- .../web/component/data/MultiButtonPanel.java | 9 ++ .../data/column/MultiButtonColumn.java | 9 ++ .../admin/certification/PageCertCampaign.java | 35 ++++--- .../certification/PageCertDecisions.java | 75 ++++++++++----- .../helpers/AvailableResponses.java | 95 +++++++++++++++++++ .../localization/Midpoint_en_US.properties | 7 +- .../common/SystemConfigurationHolder.java | 9 ++ .../xml/ns/public/common/common-3.xsd | 59 ++++++++++++ .../RAccessCertificationDefinition.java | 62 +++++++++++- .../container/RAccessCertificationCase.java | 3 + 10 files changed, 313 insertions(+), 50 deletions(-) create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/helpers/AvailableResponses.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/MultiButtonPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/MultiButtonPanel.java index 6dea40e1cfd..819b5b8077c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/MultiButtonPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/MultiButtonPanel.java @@ -55,6 +55,10 @@ public void onClick(AjaxRequestTarget target) { public boolean isEnabled(){ return MultiButtonPanel.this.isButtonEnabled(finalId, MultiButtonPanel.this.getModel()); } + @Override + public boolean isVisible(){ + return MultiButtonPanel.this.isButtonVisible(finalId, MultiButtonPanel.this.getModel()); + } }; button.add(new AttributeAppender("class", getButtonCssClass(finalId))); buttons.add(button); @@ -70,6 +74,11 @@ public boolean isButtonEnabled(int id, IModel model) { return true; } + public boolean isButtonVisible(int id, IModel model) { + return true; + } + + private String getButtonCssClass(int id) { StringBuilder sb = new StringBuilder(); sb.append(DoubleButtonColumn.BUTTON_BASE_CLASS).append(" "); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/MultiButtonColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/MultiButtonColumn.java index d98418f3b95..2dfe0798a1f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/MultiButtonColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/MultiButtonColumn.java @@ -59,6 +59,11 @@ public boolean isButtonEnabled(int id, IModel model) { return MultiButtonColumn.this.isButtonEnabled(id, model); } + @Override + public boolean isButtonVisible(int id, IModel model) { + return MultiButtonColumn.this.isButtonVisible(id, model); + } + @Override public String getButtonSizeCssClass(int id) { return MultiButtonColumn.this.getButtonSizeCssClass(id); @@ -83,6 +88,10 @@ public boolean isButtonEnabled(int id, IModel model) { return true; } + public boolean isButtonVisible(int id, IModel model) { + return true; + } + public String getCaption(int id) { return String.valueOf(id); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java index 5ab91f90a86..503ed227529 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertCampaign.java @@ -38,6 +38,8 @@ import com.evolveum.midpoint.web.page.admin.certification.dto.CertCampaignDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertCaseDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertCaseDtoProvider; +import com.evolveum.midpoint.web.page.admin.certification.dto.CertDecisionDto; +import com.evolveum.midpoint.web.page.admin.certification.helpers.AvailableResponses; import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.WebMiscUtil; @@ -292,24 +294,14 @@ private List> initColumns() { column = new PropertyColumn(createStringResource("PageCertCampaign.table.reviewedInStage"), CertCaseDto.F_CURRENT_RESPONSE_STAGE_NUMBER); columns.add(column); - column = new MultiButtonColumn(new Model(), 6) { + final AvailableResponses availableResponses = new AvailableResponses(getPage()); + final int responses = availableResponses.getCount(); - private final String[] captionKeys = { - "PageCertCampaign.menu.accept", - "PageCertCampaign.menu.revoke", - "PageCertCampaign.menu.reduce", - "PageCertCampaign.menu.notDecided", - "PageCertCampaign.menu.delegate", - "PageCertCampaign.menu.noResponse" - }; - - private final AccessCertificationResponseType[] responses = { - ACCEPT, REVOKE, REDUCE, NOT_DECIDED, DELEGATE, NO_RESPONSE - }; + column = new MultiButtonColumn(new Model(), responses+1) { @Override public String getCaption(int id) { - return PageCertCampaign.this.createStringResource(captionKeys[id]).getString(); + return availableResponses.getCaption(id); } @Override @@ -317,9 +309,22 @@ public boolean isButtonEnabled(int id, IModel model) { return false; } + @Override + public boolean isButtonVisible(int id, IModel model) { + if (id < responses) { + return true; + } else { + return !availableResponses.isAvailable(model.getObject().getCurrentResponse()); + } + } + @Override public String getButtonColorCssClass(int id) { - return getDecisionButtonColor(getRowModel(), responses[id]); + if (id < responses) { + return getDecisionButtonColor(getRowModel(), availableResponses.getResponseValues().get(id)); + } else { + return BUTTON_COLOR_CLASS.DANGER.toString(); + } } }; columns.add(column); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java index 3c6cb675360..07e6252ac4f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDecisions.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.web.page.admin.certification; +import com.evolveum.midpoint.common.SystemConfigurationHolder; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.result.OperationResult; @@ -33,13 +34,16 @@ import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; import com.evolveum.midpoint.web.page.admin.certification.dto.CertDecisionDto; import com.evolveum.midpoint.web.page.admin.certification.dto.CertDecisionDtoProvider; +import com.evolveum.midpoint.web.page.admin.certification.helpers.AvailableResponses; import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction; import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.TooltipBehavior; import com.evolveum.midpoint.web.util.WebMiscUtil; +import com.evolveum.midpoint.web.util.WebModelUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import org.apache.wicket.AttributeModifier; @@ -262,40 +266,49 @@ public void populateItem(Item> item, String comp }; columns.add(column); - column = new MultiButtonColumn(new Model(), 6) { + final AvailableResponses availableResponses = new AvailableResponses(getPage()); + final int responses = availableResponses.getResponseKeys().size(); - private final String[] captionKeys = { - "PageCertDecisions.menu.accept", - "PageCertDecisions.menu.revoke", - "PageCertDecisions.menu.reduce", - "PageCertDecisions.menu.notDecided", - "PageCertDecisions.menu.delegate", - "PageCertDecisions.menu.noResponse" - }; - - private final AccessCertificationResponseType[] responses = { - ACCEPT, REVOKE, REDUCE, NOT_DECIDED, DELEGATE, NO_RESPONSE - }; + column = new MultiButtonColumn(new Model(), responses+1) { @Override public String getCaption(int id) { - return PageCertDecisions.this.createStringResource(captionKeys[id]).getString(); + return availableResponses.getCaption(id); } @Override public boolean isButtonEnabled(int id, IModel model) { - return !decisionEquals(model, responses[id]); + if (id < responses) { + return !decisionEquals(model, availableResponses.getResponseValues().get(id)); + } else { + return false; + } + } + + @Override + public boolean isButtonVisible(int id, IModel model) { + if (id < responses) { + return true; + } else { + return !availableResponses.isAvailable(model.getObject().getResponse()); + } } @Override public String getButtonColorCssClass(int id) { - return getDecisionButtonColor(getRowModel(), responses[id]); + if (id < responses) { + return getDecisionButtonColor(getRowModel(), availableResponses.getResponseValues().get(id)); + } else { + return BUTTON_COLOR_CLASS.DANGER.toString(); + } } @Override public void clickPerformed(int id, AjaxRequestTarget target, IModel model) { - recordActionPerformed(target, model.getObject(), responses[id]); + if (id < responses) { // should be always the case + recordActionPerformed(target, model.getObject(), availableResponses.getResponseValues().get(id)); + } } }; @@ -312,19 +325,31 @@ public void onBlur(AjaxRequestTarget target, IModel model) { }; columns.add(column); - columns.add(new InlineMenuHeaderColumn(createInlineMenu())); + columns.add(new InlineMenuHeaderColumn(createInlineMenu(availableResponses))); return columns; } - private List createInlineMenu() { + private List createInlineMenu(AvailableResponses availableResponses) { List items = new ArrayList<>(); - items.add(createMenu("PageCertDecisions.menu.acceptSelected", ACCEPT)); - items.add(createMenu("PageCertDecisions.menu.revokeSelected", REVOKE)); - items.add(createMenu("PageCertDecisions.menu.reduceSelected", REDUCE)); - items.add(createMenu("PageCertDecisions.menu.notDecidedSelected", NOT_DECIDED)); - items.add(createMenu("PageCertDecisions.menu.delegateSelected", DELEGATE)); - items.add(createMenu("PageCertDecisions.menu.noResponseSelected", NO_RESPONSE)); + if (availableResponses.isAvailable(ACCEPT)) { + items.add(createMenu("PageCertDecisions.menu.acceptSelected", ACCEPT)); + } + if (availableResponses.isAvailable(REVOKE)) { + items.add(createMenu("PageCertDecisions.menu.revokeSelected", REVOKE)); + } + if (availableResponses.isAvailable(REDUCE)) { + items.add(createMenu("PageCertDecisions.menu.reduceSelected", REDUCE)); + } + if (availableResponses.isAvailable(NOT_DECIDED)) { + items.add(createMenu("PageCertDecisions.menu.notDecidedSelected", NOT_DECIDED)); + } + if (availableResponses.isAvailable(DELEGATE)) { + items.add(createMenu("PageCertDecisions.menu.delegateSelected", DELEGATE)); + } + if (availableResponses.isAvailable(NO_RESPONSE)) { + items.add(createMenu("PageCertDecisions.menu.noResponseSelected", NO_RESPONSE)); + } return items; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/helpers/AvailableResponses.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/helpers/AvailableResponses.java new file mode 100644 index 00000000000..c4fe015e015 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/helpers/AvailableResponses.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.web.page.admin.certification.helpers; + +import com.evolveum.midpoint.common.SystemConfigurationHolder; +import com.evolveum.midpoint.web.page.PageBase; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; +import org.apache.wicket.Page; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.ACCEPT; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.DELEGATE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NOT_DECIDED; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.REDUCE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.REVOKE; + +/** + * TODO implement more cleanly + * + * @author mederly + */ +public class AvailableResponses implements Serializable { + + private List responseKeys; + private List responseValues; + private Page page; + + public AvailableResponses(Page page) { + this.page = page; + + AccessCertificationConfigurationType config = SystemConfigurationHolder.getCertificationConfiguration(); + + responseKeys = new ArrayList<>(6); + responseValues = new ArrayList<>(6); + + addResponse(config, "PageCertDecisions.menu.accept", ACCEPT); + addResponse(config, "PageCertDecisions.menu.revoke", REVOKE); + addResponse(config, "PageCertDecisions.menu.reduce", REDUCE); + addResponse(config, "PageCertDecisions.menu.notDecided", NOT_DECIDED); + addResponse(config, "PageCertDecisions.menu.delegate", DELEGATE); + addResponse(config, "PageCertDecisions.menu.noResponse", NO_RESPONSE); + } + + public List getResponseKeys() { + return responseKeys; + } + + public List getResponseValues() { + return responseValues; + } + + private void addResponse(AccessCertificationConfigurationType config, String captionKey, AccessCertificationResponseType response) { + if (config != null && !config.getAvailableResponse().isEmpty() && !config.getAvailableResponse().contains(response)) { + return; + } + responseKeys.add(captionKey); + responseValues.add(response); + } + + + public boolean isAvailable(AccessCertificationResponseType response) { + return response == null || responseValues.contains(response); + } + + public String getCaption(int id) { + if (id < responseKeys.size()) { + return PageBase.createStringResourceStatic(page, responseKeys.get(id)).getString(); + } else { + return PageBase.createStringResourceStatic(page, "PageCertDecisions.menu.illegalResponse").getString(); + } + } + + public int getCount() { + return responseKeys.size(); + } +} diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties b/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties index ef70132d9ec..751e5cad5aa 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint_en_US.properties @@ -1197,12 +1197,6 @@ PageCertCampaign.button.startCampaign=Start campaign PageCertCampaign.button.startRemediation=Start remediation PageCertCampaign.currentState=Current state PageCertCampaign.description=Description -PageCertCampaign.menu.accept=Accept -PageCertCampaign.menu.delegate=Delegate -PageCertCampaign.menu.noResponse=No Response -PageCertCampaign.menu.notDecided=Not Decided -PageCertCampaign.menu.reduce=Reduce -PageCertCampaign.menu.revoke=Revoke PageCertCampaign.name=Name PageCertCampaign.numberOfStages=Number of stages PageCertCampaign.owner=Owner @@ -1281,6 +1275,7 @@ PageCertDecisions.menu.reduce=Reduce PageCertDecisions.menu.reduceSelected=Reduce selected PageCertDecisions.menu.revoke=Revoke PageCertDecisions.menu.revokeSelected=Revoke selected +PageCertDecisions.menu.illegalResponse=Illegal Response PageCertDecisions.message.noItemSelected=No item selected PageCertDecisions.now=now PageCertDecisions.subTitle= diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/SystemConfigurationHolder.java b/infra/common/src/main/java/com/evolveum/midpoint/common/SystemConfigurationHolder.java index 6eb8a4e8662..9ee188efc7e 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/SystemConfigurationHolder.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/SystemConfigurationHolder.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.common; import com.evolveum.midpoint.schema.util.SystemConfigurationTypeUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; /** @@ -40,4 +41,12 @@ public static void setCurrentConfiguration(SystemConfigurationType currentConfig public static boolean isExperimentalCodeEnabled() { return SystemConfigurationTypeUtil.isExperimentalCodeEnabled(currentConfiguration); } + + public static AccessCertificationConfigurationType getCertificationConfiguration() { + if (currentConfiguration != null) { + return currentConfiguration.getAccessCertification(); + } else { + return null; + } + } } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index 62abc99c14a..fe23f5e0ecc 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -8733,6 +8733,14 @@ + + + + A configuration for access certifications. + + + + @@ -12176,6 +12184,36 @@ + + + + ID that was used to auto-generate campaign name last time (null if none so far). + + + + + + + When the last campaign of this type was started? + + + + + + + When the last campaign of this type was closed? Deletion is not recorded in this attribute. + + + + + + + How often should a campaign of this type be automatically started? + (null if automated scheduling is not required) + Scheduling is based on last campaign started timestamp. + + + @@ -13244,6 +13282,27 @@ + + + + Configuration for access certification. + + + + + + + + + + What response types are available to reviewers? Empty list means all responses. + TODO should we configure also names of the responses? (probably no) + + + + + + diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java index c0c89c6a8d6..fc74ecc0f3a 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.repo.sql.data.common; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.repo.sql.data.common.embedded.REmbeddedReference; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.IdGeneratorResult; @@ -30,6 +31,7 @@ import javax.persistence.Entity; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import javax.xml.datatype.XMLGregorianCalendar; import java.util.Collection; @Entity @@ -41,6 +43,11 @@ public class RAccessCertificationDefinition extends RObject Date: Thu, 10 Dec 2015 17:38:25 +0100 Subject: [PATCH 095/116] DB scripts for new cert definition attributes. --- config/sql/midpoint/3.3/h2/h2-3.4.sql | 15 +++++++++++---- .../sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql | 8 ++++++++ config/sql/midpoint/3.3/mysql/mysql-3.4.sql | 17 ++++++++++++----- .../3.3/mysql/mysql-upgrade-3.3-3.4.sql | 9 +++++++++ config/sql/midpoint/3.3/oracle/oracle-3.4.sql | 15 +++++++++++---- .../3.3/oracle/oracle-upgrade-3.3-3.4.sql | 9 +++++++++ .../midpoint/3.3/postgresql/postgresql-3.4.sql | 13 ++++++++++--- .../postgresql/postgresql-upgrade-3.3-3.4.sql | 9 +++++++++ .../midpoint/3.3/sqlserver/sqlserver-3.4.sql | 15 +++++++++++---- .../3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql | 9 +++++++++ 10 files changed, 99 insertions(+), 20 deletions(-) diff --git a/config/sql/midpoint/3.3/h2/h2-3.4.sql b/config/sql/midpoint/3.3/h2/h2-3.4.sql index 1443bfa217f..dee11b7003c 100644 --- a/config/sql/midpoint/3.3/h2/h2-3.4.sql +++ b/config/sql/midpoint/3.3/h2/h2-3.4.sql @@ -82,10 +82,17 @@ CREATE TABLE m_acc_cert_decision ( ); CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) + campaignSchedulingInterval VARCHAR(255), + handlerUri VARCHAR(255), + lastCampaignClosedTimestamp TIMESTAMP, + lastCampaignStartedTimestamp TIMESTAMP, + name_norm VARCHAR(255), + name_orig VARCHAR(255), + ownerRef_relation VARCHAR(157), + ownerRef_targetOid VARCHAR(36), + ownerRef_type INTEGER, + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) ); CREATE TABLE m_assignment ( diff --git a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql index 50c60a9ec11..3aeb2c8ea0e 100644 --- a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql @@ -7,6 +7,14 @@ ALTER TABLE m_acc_cert_campaign ADD stageNumber INTEGER; ALTER TABLE m_acc_cert_campaign ADD startTimestamp TIMESTAMP; ALTER TABLE m_acc_cert_campaign ADD state INTEGER; +ALTER TABLE m_acc_cert_definition ADD campaignSchedulingInterval VARCHAR(255); +ALTER TABLE m_acc_cert_definition ADD handlerUri VARCHAR(255); +ALTER TABLE m_acc_cert_definition ADD lastCampaignClosedTimestamp TIMESTAMP; +ALTER TABLE m_acc_cert_definition ADD lastCampaignStartedTimestamp TIMESTAMP; +ALTER TABLE m_acc_cert_definition ADD ownerRef_relation VARCHAR(157); +ALTER TABLE m_acc_cert_definition ADD ownerRef_targetOid VARCHAR(36); +ALTER TABLE m_acc_cert_definition ADD ownerRef_type INTEGER; + CREATE TABLE m_acc_cert_case ( id INTEGER NOT NULL, owner_oid VARCHAR(36) NOT NULL, diff --git a/config/sql/midpoint/3.3/mysql/mysql-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql index 1a5761fe28b..1bfdfbc0d80 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-3.4.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql @@ -110,14 +110,21 @@ CREATE TABLE m_acc_cert_decision ( ENGINE = InnoDB; CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, - PRIMARY KEY (oid) + campaignSchedulingInterval VARCHAR(255), + handlerUri VARCHAR(255), + lastCampaignClosedTimestamp DATETIME(6), + lastCampaignStartedTimestamp DATETIME(6), + name_norm VARCHAR(255), + name_orig VARCHAR(255), + ownerRef_relation VARCHAR(157), + ownerRef_targetOid VARCHAR(36), + ownerRef_type INTEGER, + oid VARCHAR(36) NOT NULL, + PRIMARY KEY (oid) ) DEFAULT CHARACTER SET utf8 COLLATE utf8_bin - ENGINE=InnoDB; + ENGINE = InnoDB; CREATE TABLE m_assignment ( id INTEGER NOT NULL, diff --git a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql index 2d5b4081211..9bc89c04b31 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql @@ -8,6 +8,15 @@ ADD stageNumber INTEGER, ADD startTimestamp DATETIME(6), ADD state INTEGER; +ALTER TABLE m_acc_cert_definition +ADD campaignSchedulingInterval VARCHAR(255), +ADD handlerUri VARCHAR(255), +ADD lastCampaignClosedTimestamp DATETIME(6), +ADD lastCampaignStartedTimestamp DATETIME(6), +ADD ownerRef_relation VARCHAR(157), +ADD ownerRef_targetOid VARCHAR(36), +ADD ownerRef_type INTEGER; + CREATE TABLE m_acc_cert_case ( id INTEGER NOT NULL, owner_oid VARCHAR(36) NOT NULL, diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql index 296a44181ae..3ec84cb3fb6 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.4.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql @@ -85,10 +85,17 @@ CREATE TABLE m_acc_cert_decision ( ) INITRANS 30; CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR2(255 CHAR), - name_orig VARCHAR2(255 CHAR), - oid VARCHAR2(36 CHAR) NOT NULL, - PRIMARY KEY (oid) + campaignSchedulingInterval VARCHAR2(255 CHAR), + handlerUri VARCHAR2(255 CHAR), + lastCampaignClosedTimestamp TIMESTAMP, + lastCampaignStartedTimestamp TIMESTAMP, + name_norm VARCHAR2(255 CHAR), + name_orig VARCHAR2(255 CHAR), + ownerRef_relation VARCHAR2(157 CHAR), + ownerRef_targetOid VARCHAR2(36 CHAR), + ownerRef_type NUMBER(10, 0), + oid VARCHAR2(36 CHAR) NOT NULL, + PRIMARY KEY (oid) ) INITRANS 30; CREATE TABLE m_assignment ( diff --git a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql index 290ffc5e56a..00a5cff64c1 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql @@ -8,6 +8,15 @@ stageNumber NUMBER(10, 0), startTimestamp TIMESTAMP, state NUMBER(10, 0)); +ALTER TABLE m_acc_cert_definition ADD ( +campaignSchedulingInterval VARCHAR2(255 CHAR), +handlerUri VARCHAR2(255 CHAR), +lastCampaignClosedTimestamp TIMESTAMP, +lastCampaignStartedTimestamp TIMESTAMP, +ownerRef_relation VARCHAR2(157 CHAR), +ownerRef_targetOid VARCHAR2(36 CHAR), +ownerRef_type NUMBER(10, 0)); + CREATE TABLE m_acc_cert_case ( id NUMBER(10, 0) NOT NULL, owner_oid VARCHAR2(36 CHAR) NOT NULL, diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql index abae81cd325..aa6228727f3 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql @@ -82,9 +82,16 @@ CREATE TABLE m_acc_cert_decision ( ); CREATE TABLE m_acc_cert_definition ( - name_norm VARCHAR(255), - name_orig VARCHAR(255), - oid VARCHAR(36) NOT NULL, + campaignSchedulingInterval VARCHAR(255), + handlerUri VARCHAR(255), + lastCampaignClosedTimestamp TIMESTAMP, + lastCampaignStartedTimestamp TIMESTAMP, + name_norm VARCHAR(255), + name_orig VARCHAR(255), + ownerRef_relation VARCHAR(157), + ownerRef_targetOid VARCHAR(36), + ownerRef_type INT4, + oid VARCHAR(36) NOT NULL, PRIMARY KEY (oid) ); diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql index b3ae7a03573..921e72bda53 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql @@ -8,6 +8,15 @@ ADD stageNumber INT4, ADD startTimestamp TIMESTAMP, ADD state INT4; +ALTER TABLE m_acc_cert_definition +ADD campaignSchedulingInterval VARCHAR(255), +ADD handlerUri VARCHAR(255), +ADD lastCampaignClosedTimestamp TIMESTAMP, +ADD lastCampaignStartedTimestamp TIMESTAMP, +ADD ownerRef_relation VARCHAR(157), +ADD ownerRef_targetOid VARCHAR(36), +ADD ownerRef_type INT4; + CREATE TABLE m_acc_cert_case ( id INT4 NOT NULL, owner_oid VARCHAR(36) NOT NULL, diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql index bb8d284589b..e39babddb27 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql @@ -82,10 +82,17 @@ CREATE TABLE m_acc_cert_decision ( ); CREATE TABLE m_acc_cert_definition ( - name_norm NVARCHAR(255) COLLATE database_default, - name_orig NVARCHAR(255) COLLATE database_default, - oid NVARCHAR(36) COLLATE database_default NOT NULL, - PRIMARY KEY (oid) + campaignSchedulingInterval NVARCHAR(255) COLLATE database_default, + handlerUri NVARCHAR(255) COLLATE database_default, + lastCampaignClosedTimestamp DATETIME2, + lastCampaignStartedTimestamp DATETIME2, + name_norm NVARCHAR(255) COLLATE database_default, + name_orig NVARCHAR(255) COLLATE database_default, + ownerRef_relation NVARCHAR(157) COLLATE database_default, + ownerRef_targetOid NVARCHAR(36) COLLATE database_default, + ownerRef_type INT, + oid NVARCHAR(36) COLLATE database_default NOT NULL, + PRIMARY KEY (oid) ); CREATE TABLE m_assignment ( diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql index de540e0c2fe..d4119b98c3e 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql @@ -8,6 +8,15 @@ stageNumber INT, startTimestamp DATETIME2, state INT; +ALTER TABLE m_acc_cert_definition ADD +campaignSchedulingInterval NVARCHAR(255) COLLATE database_default, +handlerUri NVARCHAR(255) COLLATE database_default, +lastCampaignClosedTimestamp DATETIME2, +lastCampaignStartedTimestamp DATETIME2, +ownerRef_relation NVARCHAR(157) COLLATE database_default, +ownerRef_targetOid NVARCHAR(36) COLLATE database_default, +ownerRef_type INT; + CREATE TABLE m_acc_cert_case ( id INT NOT NULL, owner_oid NVARCHAR(36) COLLATE database_default NOT NULL, From 478dd6e789a8c6b754a53d672233f05c86a2e68c Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Dec 2015 23:28:57 +0100 Subject: [PATCH 096/116] Campaign scheduling (MID-2729). Removing schedule interval from campaign definition, as the scheduling is done via task manager. --- config/sql/midpoint/3.3/h2/h2-3.4.sql | 1 - .../midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql | 1 - config/sql/midpoint/3.3/mysql/mysql-3.4.sql | 1 - .../3.3/mysql/mysql-upgrade-3.3-3.4.sql | 1 - config/sql/midpoint/3.3/oracle/oracle-3.4.sql | 1 - .../3.3/oracle/oracle-upgrade-3.3-3.4.sql | 1 - .../3.3/postgresql/postgresql-3.4.sql | 1 - .../postgresql/postgresql-upgrade-3.3-3.4.sql | 1 - .../midpoint/3.3/sqlserver/sqlserver-3.4.sql | 1 - .../sqlserver/sqlserver-upgrade-3.3-3.4.sql | 1 - .../evolveum/midpoint/web/page/PageBase.java | 6 + .../certification/PageCertDefinitions.java | 2 +- .../web/page/admin/server/PageTasks.java | 25 ++- .../localization/Midpoint.properties | 1 + .../xml/ns/public/common/common-3.xsd | 20 +-- .../api/CertificationManager.java | 4 +- .../impl/AccCertGeneralHelper.java | 11 +- .../impl/AccCertUpdateHelper.java | 15 ++ ...tificationCampaignCreationTaskHandler.java | 145 ++++++++++++++++++ .../impl/CertificationManagerImpl.java | 12 +- .../test/BasicCertificationTest.java | 2 +- .../test/CriticalRolesCertificationTest.java | 2 +- .../test/RoleInducementCertificationTest.java | 2 +- .../sql-procedures/mysql.sql | 3 + .../sql-procedures/postgresql.sql | 3 + .../sql-procedures/sqlserver.sql | 3 + .../RAccessCertificationDefinition.java | 17 +- .../start-all-user-assignments.xml | 43 ++++++ .../certification/start-role-inducements.xml | 43 ++++++ 29 files changed, 325 insertions(+), 44 deletions(-) create mode 100644 model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCampaignCreationTaskHandler.java create mode 100644 samples/certification/start-all-user-assignments.xml create mode 100644 samples/certification/start-role-inducements.xml diff --git a/config/sql/midpoint/3.3/h2/h2-3.4.sql b/config/sql/midpoint/3.3/h2/h2-3.4.sql index dee11b7003c..4413f5a1c04 100644 --- a/config/sql/midpoint/3.3/h2/h2-3.4.sql +++ b/config/sql/midpoint/3.3/h2/h2-3.4.sql @@ -82,7 +82,6 @@ CREATE TABLE m_acc_cert_decision ( ); CREATE TABLE m_acc_cert_definition ( - campaignSchedulingInterval VARCHAR(255), handlerUri VARCHAR(255), lastCampaignClosedTimestamp TIMESTAMP, lastCampaignStartedTimestamp TIMESTAMP, diff --git a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql index 3aeb2c8ea0e..68a4e406a62 100644 --- a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql @@ -7,7 +7,6 @@ ALTER TABLE m_acc_cert_campaign ADD stageNumber INTEGER; ALTER TABLE m_acc_cert_campaign ADD startTimestamp TIMESTAMP; ALTER TABLE m_acc_cert_campaign ADD state INTEGER; -ALTER TABLE m_acc_cert_definition ADD campaignSchedulingInterval VARCHAR(255); ALTER TABLE m_acc_cert_definition ADD handlerUri VARCHAR(255); ALTER TABLE m_acc_cert_definition ADD lastCampaignClosedTimestamp TIMESTAMP; ALTER TABLE m_acc_cert_definition ADD lastCampaignStartedTimestamp TIMESTAMP; diff --git a/config/sql/midpoint/3.3/mysql/mysql-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql index 1bfdfbc0d80..22eb6e4d15c 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-3.4.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql @@ -110,7 +110,6 @@ CREATE TABLE m_acc_cert_decision ( ENGINE = InnoDB; CREATE TABLE m_acc_cert_definition ( - campaignSchedulingInterval VARCHAR(255), handlerUri VARCHAR(255), lastCampaignClosedTimestamp DATETIME(6), lastCampaignStartedTimestamp DATETIME(6), diff --git a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql index 9bc89c04b31..49ada7b3afd 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql @@ -9,7 +9,6 @@ ADD startTimestamp DATETIME(6), ADD state INTEGER; ALTER TABLE m_acc_cert_definition -ADD campaignSchedulingInterval VARCHAR(255), ADD handlerUri VARCHAR(255), ADD lastCampaignClosedTimestamp DATETIME(6), ADD lastCampaignStartedTimestamp DATETIME(6), diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql index 3ec84cb3fb6..34b820be0d7 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.4.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql @@ -85,7 +85,6 @@ CREATE TABLE m_acc_cert_decision ( ) INITRANS 30; CREATE TABLE m_acc_cert_definition ( - campaignSchedulingInterval VARCHAR2(255 CHAR), handlerUri VARCHAR2(255 CHAR), lastCampaignClosedTimestamp TIMESTAMP, lastCampaignStartedTimestamp TIMESTAMP, diff --git a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql index 00a5cff64c1..94b254d0db2 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql @@ -9,7 +9,6 @@ startTimestamp TIMESTAMP, state NUMBER(10, 0)); ALTER TABLE m_acc_cert_definition ADD ( -campaignSchedulingInterval VARCHAR2(255 CHAR), handlerUri VARCHAR2(255 CHAR), lastCampaignClosedTimestamp TIMESTAMP, lastCampaignStartedTimestamp TIMESTAMP, diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql index aa6228727f3..a7ab32e12d2 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql @@ -82,7 +82,6 @@ CREATE TABLE m_acc_cert_decision ( ); CREATE TABLE m_acc_cert_definition ( - campaignSchedulingInterval VARCHAR(255), handlerUri VARCHAR(255), lastCampaignClosedTimestamp TIMESTAMP, lastCampaignStartedTimestamp TIMESTAMP, diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql index 921e72bda53..7bfa6c85e89 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql @@ -9,7 +9,6 @@ ADD startTimestamp TIMESTAMP, ADD state INT4; ALTER TABLE m_acc_cert_definition -ADD campaignSchedulingInterval VARCHAR(255), ADD handlerUri VARCHAR(255), ADD lastCampaignClosedTimestamp TIMESTAMP, ADD lastCampaignStartedTimestamp TIMESTAMP, diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql index e39babddb27..45be4960f8b 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql @@ -82,7 +82,6 @@ CREATE TABLE m_acc_cert_decision ( ); CREATE TABLE m_acc_cert_definition ( - campaignSchedulingInterval NVARCHAR(255) COLLATE database_default, handlerUri NVARCHAR(255) COLLATE database_default, lastCampaignClosedTimestamp DATETIME2, lastCampaignStartedTimestamp DATETIME2, diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql index d4119b98c3e..cf0e3dd9250 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql @@ -9,7 +9,6 @@ startTimestamp DATETIME2, state INT; ALTER TABLE m_acc_cert_definition ADD -campaignSchedulingInterval NVARCHAR(255) COLLATE database_default, handlerUri NVARCHAR(255) COLLATE database_default, lastCampaignClosedTimestamp DATETIME2, lastCampaignStartedTimestamp DATETIME2, diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java index ecaad1e5809..e4a4cd7ddff 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/PageBase.java @@ -33,6 +33,7 @@ import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.midpoint.security.api.SecurityEnforcer; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskCategory; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.Holder; import com.evolveum.midpoint.util.logging.Trace; @@ -473,6 +474,11 @@ private MainMenuItem createCertificationItems() { menu = new MenuItem(createStringResource("PageAdmin.menu.top.certification.campaigns"), PageCertCampaigns.class); submenu.add(menu); + PageParameters params = new PageParameters(); + params.add(PageTasks.SELECTED_CATEGORY, TaskCategory.ACCESS_CERTIFICATION); + menu = new MenuItem(createStringResource("PageAdmin.menu.top.certification.scheduling"), + PageTasks.class, params, null); + submenu.add(menu); menu = new MenuItem(createStringResource("PageAdmin.menu.top.certification.decisions"), PageCertDecisions.class); submenu.add(menu); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java index 333779c4ad8..d9cff67537d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/PageCertDefinitions.java @@ -227,7 +227,7 @@ private void createCampaignPerformed(AjaxRequestTarget target, AccessCertificati OperationResult result = new OperationResult(OPERATION_CREATE_CAMPAIGN); try { Task task = createSimpleTask(OPERATION_CREATE_CAMPAIGN); - getCertificationManager().createCampaign(definition, null, task, result); + getCertificationManager().createCampaign(definition.getOid(), null, task, result); } catch (Exception ex) { result.recordFatalError(ex); } finally { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java index a5c6dd48ded..34e657bc4c0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java @@ -75,6 +75,7 @@ import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.util.string.StringValue; import java.util.*; @@ -120,6 +121,8 @@ public class PageTasks extends PageAdminTasks { private static final String ID_DELETE_TASKS_POPUP = "deleteTasksPopup"; private static final String ID_TABLE_HEADER = "tableHeader"; + public static final String SELECTED_CATEGORY = "category"; + private IModel searchModel; private String searchText = ""; @@ -128,14 +131,23 @@ public PageTasks() { } public PageTasks(boolean clearSessionStorage) { - this(true, ""); + this(true, "", null); } public PageTasks(String searchText) { - this(true, searchText); + this(true, searchText, null); + } + + public PageTasks(PageParameters parameters) { + this(true, "", parameters); } - public PageTasks(boolean clearSessionStorage, String searchText) { + // TODO clean the mess with constructors + public PageTasks(boolean clearSessionStorage, String searchText, PageParameters parameters) { + if (parameters != null) { + getPageParameters().overwriteWith(parameters); + } + this.searchText = searchText; searchModel = new LoadableModel(false) { @@ -158,6 +170,13 @@ private TasksSearchDto loadTasksSearchDto() { dto.setShowSubtasks(false); } + if (getPageParameters() != null) { + StringValue category = getPageParameters().get(SELECTED_CATEGORY); + if (category != null && category.toString() != null && !category.toString().isEmpty()) { + dto.setCategory(category.toString()); + } + } + if (dto.getStatus() == null) { dto.setStatus(TaskDtoExecutionStatusFilter.ALL); } diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index 471953037a1..ce299b4daa6 100644 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -1055,6 +1055,7 @@ pageAdmin.configuration.description=Security, logging, import pageAdmin.home.description=Start here pageAdmin.home=Home PageAdmin.menu.top.certification.campaigns=Campaigns +PageAdmin.menu.top.certification.scheduling=Campaigns scheduling PageAdmin.menu.top.certification=Certification PageAdmin.menu.top.certification.decisions=My cases to decide PageAdmin.menu.top.certification.definitions=Campaign definitions diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index fe23f5e0ecc..7b02b668d3a 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -12195,6 +12195,7 @@ When the last campaign of this type was started? + CURRENTLY NOT USED. @@ -12202,18 +12203,19 @@ When the last campaign of this type was closed? Deletion is not recorded in this attribute. + CURRENTLY NOT USED. - - - - How often should a campaign of this type be automatically started? - (null if automated scheduling is not required) - Scheduling is based on last campaign started timestamp. - - - + + + + + + + + + diff --git a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java index 913fd65407f..b20cc092fed 100644 --- a/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java +++ b/model/certification-api/src/main/java/com/evolveum/midpoint/certification/api/CertificationManager.java @@ -70,14 +70,14 @@ public interface CertificationManager { * * The campaign will NOT be started upon creation. It should be started explicitly by calling openNextStage method. * - * @param certificationDefinition Certification definition for this campaign. + * @param definitionOid OID of certification definition for this campaign. * @param campaign Specific values for this campaign (optional). * It must not be persistent, i.e. its OID must not be set. * @param task Task in context of which all operations will take place. * @param parentResult Result for the operations. * @return Object for the created campaign. It will be stored in the repository as well. */ - AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType certificationDefinition, AccessCertificationCampaignType campaign, Task task, OperationResult parentResult) + AccessCertificationCampaignType createCampaign(String definitionOid, AccessCertificationCampaignType campaign, Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PolicyViolationException; /** diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java index 732f29f61ec..a79a01bc236 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertGeneralHelper.java @@ -73,7 +73,7 @@ public class AccCertGeneralHelper { protected RepositoryService repositoryService; @Autowired - private CertificationManagerImpl certificationManager; + private AccCertUpdateHelper updateHelper; private PrismObjectDefinition campaignObjectDefinition = null; // lazily evaluated @@ -104,7 +104,7 @@ AccessCertificationCampaignType createCampaignObject(AccessCertificationDefiniti if (campaign != null && campaign.getName() != null) { campaign.setName(campaign.getName()); } else if (definition != null && definition.getName() != null) { - newCampaign.setName(generateCampaignName(definition.getName().getOrig(), task, result)); + newCampaign.setName(generateCampaignName(definition, task, result)); } else { throw new SchemaException("Couldn't create a campaign without name"); } @@ -168,10 +168,13 @@ AccessCertificationCampaignType createCampaignObject(AccessCertificationDefiniti return newCampaign; } - private PolyStringType generateCampaignName(String prefix, Task task, OperationResult result) throws SchemaException { - for (int i = 1;; i++) { + private PolyStringType generateCampaignName(AccessCertificationDefinitionType definition, Task task, OperationResult result) throws SchemaException { + String prefix = definition.getName().getOrig(); + Integer lastCampaignIdUsed = definition.getLastCampaignIdUsed() != null ? definition.getLastCampaignIdUsed() : 0; + for (int i = lastCampaignIdUsed+1;; i++) { String name = generateName(prefix, i); if (!campaignExists(name, task, result)) { + updateHelper.recordLastCampaignIdUsed(definition.getOid(), i, task, result); return new PolyStringType(name); } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java index c170075a179..125926cab61 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java @@ -31,6 +31,7 @@ import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.parser.QueryConvertor; import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; @@ -56,12 +57,14 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationObjectBasedScopeType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationReviewerSpecificationType; @@ -84,12 +87,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.List; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.CLOSED; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REVIEW_STAGE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.REVIEW_STAGE_DONE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType.F_LAST_CAMPAIGN_ID_USED; /** * @author mederly @@ -629,4 +634,14 @@ public void markCaseAsRemedied(String campaignOid, long caseId, Task task, Opera repositoryService.modifyObject(AccessCertificationCampaignType.class, campaignOid, Arrays.asList(reviewRemediedDelta), parentResult); } + public void recordLastCampaignIdUsed(String definitionOid, int lastIdUsed, Task task, OperationResult result) { + try { + List modifications = DeltaBuilder.deltaFor(AccessCertificationDefinitionType.class, prismContext) + .item(F_LAST_CAMPAIGN_ID_USED).replace(lastIdUsed) + .asItemDeltas(); + repositoryService.modifyObject(AccessCertificationDefinitionType.class, definitionOid, modifications, result); + } catch (SchemaException|ObjectNotFoundException|RuntimeException|ObjectAlreadyExistsException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't update last campaign ID for definition {}", e, definitionOid); + } + } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCampaignCreationTaskHandler.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCampaignCreationTaskHandler.java new file mode 100644 index 00000000000..d71e1f57e83 --- /dev/null +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationCampaignCreationTaskHandler.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.certification.impl; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskCategory; +import com.evolveum.midpoint.task.api.TaskHandler; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.task.api.TaskRunResult; +import com.evolveum.midpoint.task.api.TaskRunResult.TaskRunResultStatus; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.List; + +/** + * The task handler for automatic campaign start. + * + * @author mederly + */ +@Component +public class AccessCertificationCampaignCreationTaskHandler implements TaskHandler { + + public static final String HANDLER_URI = AccessCertificationConstants.NS_CERTIFICATION_TASK_PREFIX + "/campaign-creation/handler-3"; + + public static final String CLASS_DOT = AccessCertificationCampaignCreationTaskHandler.class.getName() + "."; + + @Autowired + private TaskManager taskManager; + + @Autowired + private PrismContext prismContext; + + @Autowired + private CertificationManagerImpl certificationManager; + + private static final transient Trace LOGGER = TraceManager.getTrace(AccessCertificationCampaignCreationTaskHandler.class); + + @PostConstruct + private void initialize() { + taskManager.registerHandler(HANDLER_URI, this); + } + + @Override + public TaskRunResult run(Task task) { + LOGGER.trace("Task run starting"); + + long progress = task.getProgress(); + OperationResult opResult = new OperationResult(CLASS_DOT+"run"); + opResult.setSummarizeSuccesses(true); + TaskRunResult runResult = new TaskRunResult(); + runResult.setOperationResult(opResult); + + String definitionOid = task.getObjectOid(); + if (definitionOid == null) { + LOGGER.error("No definition OID specified in the task"); + opResult.recordFatalError("No definition OID specified in the task"); + runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); + return runResult; + } + + opResult.addContext("definitionOid", definitionOid); + + long started = 0; + String campaignName = null; + String campaignOid = null; + try { + task.startCollectingOperationStatsFromStoredValues(true, false, false); + + LOGGER.info("Creating campaign with definition of {}", definitionOid); + AccessCertificationCampaignType campaign = certificationManager.createCampaign(definitionOid, null, task, opResult); + LOGGER.info("Campaign {} was created.", ObjectTypeUtil.toShortString(campaign)); + + // TODO split this try-catch to two pieces in order to correctly work with iterative op failure recording + started = System.currentTimeMillis(); + campaignName = campaign.getName().getOrig(); + campaignOid = campaign.getOid(); + task.recordIterativeOperationStart(campaignName, campaignName, AccessCertificationCampaignType.COMPLEX_TYPE, campaignOid); + + certificationManager.openNextStage(campaign.getOid(), 1, task, opResult); + LOGGER.info("Campaign {} was started.", ObjectTypeUtil.toShortString(campaign)); + + task.recordIterativeOperationEnd(campaignName, campaignName, AccessCertificationCampaignType.COMPLEX_TYPE, campaignOid, started, null); + + opResult.computeStatus(); + runResult.setRunResultStatus(TaskRunResultStatus.FINISHED); + runResult.setProgress(progress+1); + return runResult; + + } catch (Exception e) { // TODO better error handling + if (campaignOid != null) { + task.recordIterativeOperationEnd(campaignName, campaignName, AccessCertificationCampaignType.COMPLEX_TYPE, campaignOid, started, e); + } + LoggingUtils.logException(LOGGER, "Error while executing 'create campaign' task handler", e); + opResult.recordFatalError("Error while executing 'create campaign' task handler: "+e.getMessage(), e); + runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); + runResult.setProgress(progress); + return runResult; + } finally { + task.storeOperationStats(); + } + } + + @Override + public Long heartbeat(Task task) { + return null; // not to reset progress information + } + + @Override + public void refreshStatus(Task task) { + // Do nothing. Everything is fresh already. + } + + @Override + public String getCategoryName(Task task) { + return TaskCategory.ACCESS_CERTIFICATION; + } + + @Override + public List getCategoryNames() { + return null; + } +} diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java index 04a27132efd..56ef201a5a0 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/CertificationManagerImpl.java @@ -136,17 +136,21 @@ public CertificationHandler findCertificationHandler(AccessCertificationCampaign } @Override - public AccessCertificationCampaignType createCampaign(AccessCertificationDefinitionType certDefinition, AccessCertificationCampaignType campaign, + public AccessCertificationCampaignType createCampaign(String definitionOid, AccessCertificationCampaignType campaign, Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PolicyViolationException { Validate.notNull(task, "task"); Validate.notNull(parentResult, "parentResult"); - if (certDefinition == null && campaign == null) { - throw new IllegalArgumentException("Both certDefinition and campaign are null"); + if (definitionOid == null && campaign == null) { + throw new IllegalArgumentException("Both definitionOid and campaign are null"); } OperationResult result = parentResult.createSubresult(OPERATION_CREATE_CAMPAIGN); try { - AccessCertificationCampaignType newCampaign = helper.createCampaignObject(certDefinition, campaign, task, result); + AccessCertificationDefinitionType definition = null; + if (definitionOid != null) { + definition = modelService.getObject(AccessCertificationDefinitionType.class, definitionOid, null, task, result).asObjectable(); + } + AccessCertificationCampaignType newCampaign = helper.createCampaignObject(definition, campaign, task, result); updateHelper.addObject(newCampaign, task, result); return newCampaign; } catch (RuntimeException e) { diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java index 215fd5d55d9..1f741be1a31 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/BasicCertificationTest.java @@ -99,7 +99,7 @@ public void test010CreateCampaign() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); AccessCertificationCampaignType campaign = - certificationManager.createCampaign(certificationDefinition, null, task, result); + certificationManager.createCampaign(certificationDefinition.getOid(), null, task, result); // THEN TestUtil.displayThen(TEST_NAME); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java index 3437e6a6faa..13f34bdbc06 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/CriticalRolesCertificationTest.java @@ -98,7 +98,7 @@ public void test010CreateCampaign() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); AccessCertificationCampaignType campaign = - certificationManager.createCampaign(certificationDefinition, null, task, result); + certificationManager.createCampaign(certificationDefinition.getOid(), null, task, result); // THEN TestUtil.displayThen(TEST_NAME); diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java index 1e676ad305a..d4f37deb5bd 100644 --- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java +++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/RoleInducementCertificationTest.java @@ -85,7 +85,7 @@ public void test010CreateCampaign() throws Exception { // WHEN TestUtil.displayWhen(TEST_NAME); AccessCertificationCampaignType campaign = - certificationManager.createCampaign(certificationDefinition, null, task, result); + certificationManager.createCampaign(certificationDefinition.getOid(), null, task, result); // THEN TestUtil.displayThen(TEST_NAME); diff --git a/repo/repo-sql-impl-test/sql-procedures/mysql.sql b/repo/repo-sql-impl-test/sql-procedures/mysql.sql index f90e6eb3f04..aa42476d3cc 100644 --- a/repo/repo-sql-impl-test/sql-procedures/mysql.sql +++ b/repo/repo-sql-impl-test/sql-procedures/mysql.sql @@ -9,6 +9,9 @@ DETERMINISTIC DECLARE run TINYINT DEFAULT 0; DELETE FROM m_sequence; + DELETE FROM m_acc_cert_case_reference; + DELETE FROM m_acc_cert_decision; + DELETE FROM m_acc_cert_case; DELETE FROM m_acc_cert_campaign; DELETE FROM m_acc_cert_definition; DELETE FROM m_audit_delta; diff --git a/repo/repo-sql-impl-test/sql-procedures/postgresql.sql b/repo/repo-sql-impl-test/sql-procedures/postgresql.sql index 22d07058691..d9634f2927b 100644 --- a/repo/repo-sql-impl-test/sql-procedures/postgresql.sql +++ b/repo/repo-sql-impl-test/sql-procedures/postgresql.sql @@ -2,6 +2,9 @@ CREATE OR REPLACE FUNCTION cleanupTestDatabase() RETURNS INTEGER AS $$ BEGIN TRUNCATE TABLE m_sequence RESTART IDENTITY CASCADE; + TRUNCATE TABLE m_acc_cert_case_reference RESTART IDENTITY CASCADE; + TRUNCATE TABLE m_acc_cert_decision RESTART IDENTITY CASCADE; + TRUNCATE TABLE m_acc_cert_case RESTART IDENTITY CASCADE; TRUNCATE TABLE m_acc_cert_campaign RESTART IDENTITY CASCADE; TRUNCATE TABLE m_acc_cert_definition RESTART IDENTITY CASCADE; TRUNCATE TABLE m_audit_delta RESTART IDENTITY CASCADE; diff --git a/repo/repo-sql-impl-test/sql-procedures/sqlserver.sql b/repo/repo-sql-impl-test/sql-procedures/sqlserver.sql index 11866bca38e..74cec966b2a 100644 --- a/repo/repo-sql-impl-test/sql-procedures/sqlserver.sql +++ b/repo/repo-sql-impl-test/sql-procedures/sqlserver.sql @@ -13,6 +13,9 @@ AS SET NOCOUNT ON; DELETE FROM m_sequence; + DELETE FROM m_acc_cert_case_reference; + DELETE FROM m_acc_cert_decision; + DELETE FROM m_acc_cert_case; DELETE FROM m_acc_cert_campaign; DELETE FROM m_acc_cert_definition; DELETE FROM m_audit_delta; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java index fc74ecc0f3a..c7b7b920352 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/RAccessCertificationDefinition.java @@ -47,7 +47,7 @@ public class RAccessCertificationDefinition extends RObject + + + + + Start campaign: All user assignment + + + runnable + + AccessCertification + http://midpoint.evolveum.com/xml/ns/public/certification/task/campaign-creation/handler-3 + + + + name + All user assignments + + + + recurring + loose + + 0 */5 * * * ? + + + diff --git a/samples/certification/start-role-inducements.xml b/samples/certification/start-role-inducements.xml new file mode 100644 index 00000000000..69460fac9f9 --- /dev/null +++ b/samples/certification/start-role-inducements.xml @@ -0,0 +1,43 @@ + + + + + + Start campaign: Role Inducements + + + runnable + + AccessCertification + http://midpoint.evolveum.com/xml/ns/public/certification/task/campaign-creation/handler-3 + + + + name + Role Inducements + + + + recurring + loose + + 0 0 0 * * ? + + + From ba9d50730dc1dc701244145054d4cb5ccd227c29 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 11 Dec 2015 00:13:59 +0100 Subject: [PATCH 097/116] Fixed foreign key name that was too long for Oracle (sigh) --- config/sql/midpoint/3.3/h2/h2-3.4.sql | 2 +- config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql | 2 +- config/sql/midpoint/3.3/mysql/mysql-3.4.sql | 2 +- config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql | 2 +- config/sql/midpoint/3.3/oracle/oracle-3.4.sql | 2 +- config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql | 2 +- config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql | 2 +- .../sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql | 2 +- config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql | 2 +- config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql | 2 +- .../repo/sql/data/common/container/RCertCaseReference.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/config/sql/midpoint/3.3/h2/h2-3.4.sql b/config/sql/midpoint/3.3/h2/h2-3.4.sql index 4413f5a1c04..41911ab9db3 100644 --- a/config/sql/midpoint/3.3/h2/h2-3.4.sql +++ b/config/sql/midpoint/3.3/h2/h2-3.4.sql @@ -867,7 +867,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql index 68a4e406a62..6d483a9a133 100644 --- a/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/h2/h2-upgrade-3.3-3.4.sql @@ -91,7 +91,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/mysql/mysql-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql index 22eb6e4d15c..ca95305eed5 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-3.4.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-3.4.sql @@ -1047,7 +1047,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object (oid); ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case (id, owner_oid); diff --git a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql index 49ada7b3afd..7b50b2d4e61 100644 --- a/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/mysql/mysql-upgrade-3.3-3.4.sql @@ -102,7 +102,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object (oid); ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case (id, owner_oid); diff --git a/config/sql/midpoint/3.3/oracle/oracle-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql index 34b820be0d7..0d784846f30 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-3.4.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-3.4.sql @@ -877,7 +877,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql index 94b254d0db2..47ba999f39b 100644 --- a/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/oracle/oracle-upgrade-3.3-3.4.sql @@ -93,7 +93,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql index a7ab32e12d2..6849da63075 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-3.4.sql @@ -867,7 +867,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql index 7bfa6c85e89..6016921581d 100644 --- a/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/postgresql/postgresql-upgrade-3.3-3.4.sql @@ -93,7 +93,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql index 45be4960f8b..03ef48a2faf 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-3.4.sql @@ -867,7 +867,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql index cf0e3dd9250..63e48c30399 100644 --- a/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql +++ b/config/sql/midpoint/3.3/sqlserver/sqlserver-upgrade-3.3-3.4.sql @@ -93,7 +93,7 @@ FOREIGN KEY (owner_oid) REFERENCES m_object; ALTER TABLE m_acc_cert_case_reference -ADD CONSTRAINT fk_acc_cert_case_reference_owner +ADD CONSTRAINT fk_acc_cert_case_ref_owner FOREIGN KEY (owner_id, owner_owner_oid) REFERENCES m_acc_cert_case; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java index 26bf3cee30c..70680415b25 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/container/RCertCaseReference.java @@ -70,7 +70,7 @@ public class RCertCaseReference extends RContainerReference { // return targetName; // } - @ForeignKey(name = "fk_acc_cert_case_reference_owner") + @ForeignKey(name = "fk_acc_cert_case_ref_owner") @MapsId("owner") @ManyToOne(fetch = FetchType.LAZY) @NotQueryable From 16908dec498801ef0fb31d665e134f0d3ed323f0 Mon Sep 17 00:00:00 2001 From: honchar Date: Fri, 11 Dec 2015 11:49:07 +0100 Subject: [PATCH 098/116] Associations editable panel --- .../web/component/prism/ContainerWrapper.java | 27 ++++----- .../web/component/prism/ObjectWrapper.java | 16 ++++- .../web/component/prism/PrismValuePanel.java | 24 +++----- .../AssociationValueChoosePanel.html | 10 ++-- .../AssociationValueChoosePanel.java | 60 ++++++------------- 5 files changed, 58 insertions(+), 79 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java index 175e08a8c13..1bf7eee55a4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java @@ -27,21 +27,12 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; -import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.prism.PrismReferenceDefinition; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; @@ -654,11 +645,15 @@ public ContainerWrapper getContainer() { return null; } - @Override - public void addValue() { - // TODO Auto-generated method stub + //TODO add new PrismContainerValue to association container + public void addValue() { + getItems().add(createItem()); + } - } + public ItemWrapper createItem() { + ValueWrapper wrapper = new ValueWrapper(this, new PrismPropertyValue(null), ValueStatus.ADDED); + return wrapper.getItem(); + } @Override public String debugDump() { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java index 4ce5b3f9806..d978f5a2e7b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java @@ -581,19 +581,31 @@ public ObjectDelta getObjectDelta() throws SchemaException { for (ContainerWrapper containerWrapper : getContainers()) { //create ContainerDelta for association container + //TODO create correct procession for association container data + //according to its structure if (containerWrapper.getItemDefinition().getName().equals(ShadowType.F_ASSOCIATION)) { ContainerDelta containerDelta = ContainerDelta.createDelta(ShadowType.F_ASSOCIATION, containerWrapper.getItemDefinition()); List itemsList = (List) containerWrapper.getItems(); + //TODO how to get the correct item (instead of index)? int index = 0; for (ItemWrapper vals : itemsList) { + List valuesList = (List) itemsList.get(index).getValues(); if (vals instanceof PropertyWrapper) { PropertyWrapper assocValue =(PropertyWrapper) vals; - if ((assocValue).getStatus() == ValueStatus.DELETED) { + if (assocValue.getStatus() == ValueStatus.DELETED) { PrismContainer prismContainer = containerWrapper.getItem(); List containerValues = prismContainer.getValues(); for (PrismContainerValue containerValue : containerValues){ if (containerValues.indexOf(containerValue) == index){ - containerDelta.addValueToDelete(containerValue); + containerDelta.addValueToDelete(containerValue.clone()); + } + } + } else if (assocValue.getStatus().equals(ValueStatus.ADDED)){ + PrismContainer prismContainer = containerWrapper.getItem(); + List containerValues = prismContainer.getValues(); + for (PrismContainerValue containerValue : containerValues){ + if (containerValues.indexOf(containerValue) == index){ + containerDelta.addValueToAdd(containerValue.clone()); } } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index 6eb28fb8e7a..0627b67def9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -26,15 +26,11 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; -import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.parser.QueryConvertor; import com.evolveum.midpoint.prism.query.*; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.page.admin.PageAdminFocus; import com.evolveum.midpoint.web.page.admin.users.component.AssociationValueChoosePanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang.ClassUtils; @@ -44,13 +40,11 @@ import org.apache.wicket.MarkupContainer; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; -import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField; import org.apache.wicket.extensions.yui.calendar.DateTimeField; import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.TextField; @@ -80,7 +74,6 @@ import com.evolveum.midpoint.web.component.input.DatePanel; import com.evolveum.midpoint.web.component.input.PasswordPanel; import com.evolveum.midpoint.web.component.input.TextAreaPanel; -import com.evolveum.midpoint.web.component.input.TextDetailsPanel; import com.evolveum.midpoint.web.component.input.TextPanel; import com.evolveum.midpoint.web.component.input.TriStateComboPanel; import com.evolveum.midpoint.web.component.input.UploadDownloadPanel; @@ -149,11 +142,7 @@ private void initLayout(IModel label, Form form, String valueCssClass, S @Override public void onClick(AjaxRequestTarget target) { Component inputPanel = this.getParent().get(ID_INPUT); - if (inputPanel instanceof AssociationValueChoosePanel) { - ((AssociationValueChoosePanel)inputPanel).editValuePerformed(target); - } else { - addValue(target); - } + addValue(target); } }; addButton.add(new VisibleEnableBehaviour() { @@ -746,10 +735,15 @@ private String getAttributeName(ResourceAttribute attr) { } private void addValue(AjaxRequestTarget target) { + Component inputPanel = this.get(ID_VALUE_CONTAINER).get(ID_INPUT); ValueWrapper wrapper = model.getObject(); ItemWrapper propertyWrapper = wrapper.getItem(); - propertyWrapper.addValue(); - + if (inputPanel instanceof AssociationValueChoosePanel) { + //TODO add new PrismContainerValue + propertyWrapper.getContainer().addValue(); + } else { + propertyWrapper.addValue(); + } ListView parent = findParent(ListView.class); target.add(parent.getParent()); } @@ -804,7 +798,7 @@ private ObjectQuery getAssociationsSearchQuery(PrismContext prismContext, PrismO ObjectFilter andFilter = AndFilter.createAnd( EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, objectClass.getRealValue()), EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class, prismContext, kind.getRealValue()), - EqualFilter.createEqual(ShadowType.F_INTENT, ShadowType.class, prismContext, intent.getRealValue()), +// EqualFilter.createEqual(ShadowType.F_INTENT, ShadowType.class, prismContext, intent.getRealValue()), RefFilter.createReferenceEqual(new ItemPath(ShadowType.F_RESOURCE_REF), ShadowType.class, prismContext, resource.getOid())); ObjectQuery query = ObjectQuery.createObjectQuery(andFilter); return query; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html index f625ef97aa6..1d66d1b607a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.html @@ -21,11 +21,11 @@
- - - - - + + +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java index 6e4a76d9fd5..cdfde587186 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java @@ -11,8 +11,7 @@ import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ItemWrapper; -import com.evolveum.midpoint.web.component.prism.ValueWrapper; +import com.evolveum.midpoint.web.component.prism.*; import com.evolveum.midpoint.web.component.util.SimplePanel; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPage; import com.evolveum.midpoint.web.page.admin.configuration.component.ObjectSelectionPanel; @@ -27,7 +26,6 @@ import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.TextField; -import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; @@ -58,8 +56,8 @@ public class AssociationValueChoosePanel extends Simpl private static final String ID_ADD = "add"; private static final String ID_REMOVE = "remove"; private static final String ID_BUTTON_GROUP = "buttonGroup"; -// private static final String ID_EDIT = "edit"; -private IModel model; + private static final String ID_EDIT = "edit"; + private IModel model; protected static final String MODAL_ID_OBJECT_SELECTION_POPUP = "objectSelectionPopup"; @@ -96,14 +94,15 @@ protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { FeedbackPanel feedback = new FeedbackPanel(ID_FEEDBACK, new ComponentFeedbackMessageFilter(text)); textWrapper.add(feedback); -// AjaxLink edit = new AjaxLink(ID_EDIT) { -// -// @Override -// public void onClick(AjaxRequestTarget target) { -// editValuePerformed(values, target); -// } -// }; -// textWrapper.add(edit); + AjaxLink edit = new AjaxLink(ID_EDIT) { + + @Override + public void onClick(AjaxRequestTarget target) { + editValuePerformed(target); + } + }; + edit.setVisible(true); + textWrapper.add(edit); add(textWrapper); initDialog(type, values); @@ -114,26 +113,12 @@ protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { // return ty; // } - protected void replaceIfEmpty(Object object) { - T old = getModelObject(); - ObjectReferenceType ort = ObjectTypeUtil.createObjectRef((ObjectType) object); - ort.setTargetName(((ObjectType) object).getName()); - if (old instanceof PrismPropertyValue) { // let's assume we are working with associations panel - IModel modelT = getModel(); - T objectT = modelT.getObject(); - if (objectT == null){ - - } - - ShadowType shadowType = (ShadowType) object; - - PrismProperty newValue = (PrismProperty)shadowType.asPrismObject().getValue().getItems().get(0); - PrismPropertyValue ppv = (PrismPropertyValue)newValue.getValues().get(0); - //TODO - getModel().setObject((T)ppv); - } else { - getModel().setObject((T) ort.asReferenceValue()); - } + protected void replace(Object object) { + //TODO be careful , non systematic hack + ShadowType shadowType = (ShadowType) object; + PrismProperty newValue = (PrismProperty) shadowType.asPrismObject().getValue().getItems().get(0); + PrismPropertyValue ppv = (PrismPropertyValue) newValue.getValues().get(0); + getModel().setObject((T) ppv); } protected void initDialog(final Class type, List values) { @@ -295,14 +280,7 @@ protected void choosePerformed(AjaxRequestTarget target, C object) { ModalWindow window = (ModalWindow) get(MODAL_ID_OBJECT_SELECTION_POPUP); window.close(target); - ValueWrapper wrapper = model.getObject(); - ItemWrapper propertyWrapper = wrapper.getItem(); - propertyWrapper.addValue(); - - ListView parent = findParent(ListView.class).findParent(ListView.class); - target.add(parent.getParent()); - - replaceIfEmpty(object); + replace(object); if (LOGGER.isTraceEnabled()) { LOGGER.trace("New object instance has been added to the model."); From 10eb5094852fbadab09da8c9093799629276f203 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Fri, 11 Dec 2015 21:44:27 +0100 Subject: [PATCH 099/116] Fixed silly bug of QI and QI2 interchange. --- .../midpoint/repo/sql/helpers/ObjectRetriever.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java index ddaeadb77a1..39b96ffb024 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectRetriever.java @@ -608,10 +608,10 @@ public void searchObjectsIterativeAttempt(Class type, session = transactionHelper.beginReadOnlyTransaction(); RQuery rQuery; if (isUseNewQueryInterpreter(query)) { - QueryEngine engine = new QueryEngine(getConfiguration(), prismContext); + QueryEngine2 engine = new QueryEngine2(getConfiguration(), prismContext); rQuery = engine.interpret(query, type, options, false, session); } else { - QueryEngine2 engine = new QueryEngine2(getConfiguration(), prismContext); + QueryEngine engine = new QueryEngine(getConfiguration(), prismContext); rQuery = engine.interpret(query, type, options, false, session); } @@ -821,7 +821,8 @@ public String executeArbitraryQueryAttempt(String queryString, OperationResult r } private boolean isUseNewQueryInterpreter(ObjectQuery query) { - return query == null || query.isUseNewQueryInterpreter(); + //return query == null || query.isUseNewQueryInterpreter(); + return true; } From a49a323d0d54757350710af253887eeb88a81398 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Sun, 13 Dec 2015 02:01:24 +0100 Subject: [PATCH 100/116] Preliminary certification reports. (cherry picked from commit 2c74d8f17ea381a23fe880165029d402188c3429) --- .../schema/util/CertCampaignTypeUtil.java | 60 +++++++++++++++++++ .../impl/AccCertUpdateHelper.java | 22 +++++++ .../midpoint/report/impl/ReportUtils.java | 42 +++++++++++-- .../def-all-user-assignments.xml | 1 + .../certification/def-role-inducements.xml | 1 + .../report-certification-campaigns.xml | 30 ++++++++++ .../report-certification-definitions.xml | 30 ++++++++++ 7 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 samples/certification/report-certification-campaigns.xml create mode 100644 samples/certification/report-certification-definitions.xml diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java index 0af57896d96..4c954487f0f 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/CertCampaignTypeUtil.java @@ -23,6 +23,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDecisionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationRemediationStyleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationStageDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationStageType; @@ -130,4 +131,63 @@ public static void checkStageDefinitionConsistency(List caseList, int campaignStageNumber, AccessCertificationCampaignStateType state) { + int open = 0; + if (state == AccessCertificationCampaignStateType.IN_REMEDIATION || state == AccessCertificationCampaignStateType.CLOSED) { + campaignStageNumber = campaignStageNumber - 1; // move to last campaign state + } + for (AccessCertificationCaseType aCase : caseList) { + if (aCase.getCurrentStageNumber() != campaignStageNumber) { + continue; + } + open++; + } + return open; + } + + // unanswered cases = cases where one or more answers from reviewers are missing + public static int getUnansweredCases(List caseList, int campaignStageNumber, AccessCertificationCampaignStateType state) { + int unanswered = 0; + if (state == AccessCertificationCampaignStateType.IN_REMEDIATION || state == AccessCertificationCampaignStateType.CLOSED) { + campaignStageNumber = campaignStageNumber - 1; // move to last campaign state + } + for (AccessCertificationCaseType aCase : caseList) { + if (aCase.getCurrentStageNumber() != campaignStageNumber) { + continue; + } + boolean done; + if (aCase.getReviewerRef().isEmpty()) { + done = false; // no reviewers => this case cannot be 'answered' (points to a misconfiguration) + } else { + done = true; + } + // we assume that empty decision was created for each reviewer + for (AccessCertificationDecisionType decision : aCase.getDecision()) { + if (decision.getStageNumber() != aCase.getCurrentStageNumber()) { + continue; + } + if (decision.getResponse() != null && decision.getResponse() != AccessCertificationResponseType.NO_RESPONSE) { + continue; + } + done = false; + break; + } + if (!done) { + unanswered++; + } + } + return unanswered; + } + + public static int getPercentComplete(List caseList, int campaignStageNumber, AccessCertificationCampaignStateType state) { + int active = getActiveCases(caseList, campaignStageNumber, state); + if (active > 0) { + int unanswered = getUnansweredCases(caseList, campaignStageNumber, state); + return 100 * (active - unanswered) / active; + } else { + return 100; + } + } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java index 125926cab61..53ecde8dc59 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccCertUpdateHelper.java @@ -94,7 +94,9 @@ import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.CLOSED; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.IN_REVIEW_STAGE; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignStateType.REVIEW_STAGE_DONE; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType.F_LAST_CAMPAIGN_CLOSED_TIMESTAMP; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType.F_LAST_CAMPAIGN_ID_USED; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationDefinitionType.F_LAST_CAMPAIGN_STARTED_TIMESTAMP; /** * @author mederly @@ -213,6 +215,7 @@ void recordDecision(AccessCertificationCampaignType campaign, long caseId, Acces } void closeCampaign(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException { + LOGGER.info("Closing campaign {}", ObjectTypeUtil.toShortString(campaign)); int currentStageNumber = campaign.getStageNumber(); int lastStageNumber = CertCampaignTypeUtil.getNumberOfStages(campaign); AccessCertificationCampaignStateType currentState = campaign.getState(); @@ -224,10 +227,18 @@ void closeCampaign(AccessCertificationCampaignType campaign, Task task, Operatio Arrays.asList(stateDelta, stageNumberDelta, triggerDelta), result); AccessCertificationCampaignType updatedCampaign = refreshCampaign(campaign, task, result); + LOGGER.info("Updated campaign state: {}", updatedCampaign.getState()); // if (currentState == IN_REMEDIATION) { // eventHelper.onCampaignStageEnd(updatedCampaign, task, result); // } eventHelper.onCampaignEnd(updatedCampaign, task, result); + + if (campaign.getDefinitionRef() != null) { + List deltas = DeltaBuilder.deltaFor(AccessCertificationDefinitionType.class, prismContext) + .item(F_LAST_CAMPAIGN_CLOSED_TIMESTAMP).replace(XmlTypeConverter.createXMLGregorianCalendar(new Date())) + .asItemDeltas(); + repositoryService.modifyObject(AccessCertificationDefinitionType.class, campaign.getDefinitionRef().getOid(), deltas, result); + } } // TODO implement more efficiently @@ -515,6 +526,7 @@ private void updateCases(AccessCertificationCampaignType campaign, AccessCertifi void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCertificationStageType newStage, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SecurityViolationException, ConfigurationException, CommunicationException { + boolean campaignJustCreated; // some bureaucracy... stage#, state, start time, trigger List caseList = queryHelper.searchCases(campaign.getOid(), null, null, task, result); List itemDeltaList = new ArrayList<>(); @@ -525,6 +537,9 @@ void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCerti if (newStage.getNumber() == 1) { PropertyDelta startDelta = createStartTimeDelta(XmlTypeConverter.createXMLGregorianCalendar(new Date())); itemDeltaList.add(startDelta); + campaignJustCreated = true; + } else { + campaignJustCreated = false; } if (newStage.getEnd() != null) { XMLGregorianCalendar end = newStage.getEnd(); @@ -572,6 +587,13 @@ void recordMoveToNextStage(AccessCertificationCampaignType campaign, AccessCerti ObjectReferenceType reviewerRef = ObjectTypeUtil.createObjectRef(reviewerOid, ObjectTypes.USER); eventHelper.onReviewRequested(reviewerRef, cases, campaign, task, result); } + + if (campaignJustCreated && campaign.getDefinitionRef() != null) { + List deltas = DeltaBuilder.deltaFor(AccessCertificationDefinitionType.class, prismContext) + .item(F_LAST_CAMPAIGN_STARTED_TIMESTAMP).replace(XmlTypeConverter.createXMLGregorianCalendar(new Date())) + .asItemDeltas(); + repositoryService.modifyObject(AccessCertificationDefinitionType.class, campaign.getDefinitionRef().getOid(), deltas, result); + } } void recordCloseCurrentState(AccessCertificationCampaignType campaign, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, SecurityViolationException, ConfigurationException, CommunicationException { diff --git a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java index 07669253e77..62628fa6c4a 100644 --- a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java +++ b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java @@ -20,10 +20,9 @@ import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; -import com.evolveum.midpoint.prism.polystring.PolyString; + import java.io.File; import java.sql.Timestamp; import java.text.SimpleDateFormat; @@ -85,6 +84,14 @@ public static Timestamp convertDateTime(XMLGregorianCalendar dateTime) { return timestamp; } + public static String prettyPrintForReport(XMLGregorianCalendar dateTime) { + if (dateTime == null) { + return ""; + } + SimpleDateFormat formatDate = new SimpleDateFormat(); + return formatDate.format(new Date(dateTime.toGregorianCalendar().getTimeInMillis())); + } + public static String getDateTime() { Date createDate = new Date(System.currentTimeMillis()); SimpleDateFormat formatDate = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss"); @@ -213,9 +220,36 @@ public static String prettyPrintForReport(PrismContainerValue pcv) { } public static String prettyPrintForReport(PrismReferenceValue prv) { + return prettyPrintForReport(prv, true); + } + + public static String prettyPrintForReport(PrismReferenceValue prv, boolean showType) { + StringBuilder sb = new StringBuilder(); + if (showType) { + sb.append(prettyPrintForReport(prv.getTargetType())); + sb.append(": "); + } + if (prv.getTargetName() != null) { + sb.append(prv.getTargetName()); + } else { + sb.append(prv.getOid()); + } + return sb.toString(); + } + + public static String prettyPrintForReport(ObjectReferenceType prv) { + return prettyPrintForReport(prv, true); + } + + public static String prettyPrintForReport(ObjectReferenceType prv, boolean showType) { + if (prv == null) { + return ""; + } StringBuilder sb = new StringBuilder(); - sb.append(prettyPrintForReport(prv.getTargetType())); - sb.append(": "); + if (showType || prv.getTargetName() == null) { + sb.append(prettyPrintForReport(prv.getType())); + sb.append(": "); + } if (prv.getTargetName() != null) { sb.append(prv.getTargetName()); } else { diff --git a/samples/certification/def-all-user-assignments.xml b/samples/certification/def-all-user-assignments.xml index 33acdcab8c0..ccf75c5c75a 100644 --- a/samples/certification/def-all-user-assignments.xml +++ b/samples/certification/def-all-user-assignments.xml @@ -22,6 +22,7 @@ All user assignments Certifies all users' assignments. Everything is certified by the administrator. http://midpoint.evolveum.com/xml/ns/public/certification/handlers-3#direct-assignment + diff --git a/samples/certification/def-role-inducements.xml b/samples/certification/def-role-inducements.xml index c7abd783056..9ccecc096a1 100644 --- a/samples/certification/def-role-inducements.xml +++ b/samples/certification/def-role-inducements.xml @@ -26,6 +26,7 @@ false + diff --git a/samples/certification/report-certification-campaigns.xml b/samples/certification/report-certification-campaigns.xml new file mode 100644 index 00000000000..9cb57fecc3b --- /dev/null +++ b/samples/certification/report-certification-campaigns.xml @@ -0,0 +1,30 @@ + + + + + Certification campaigns + true + + html + diff --git a/samples/certification/report-certification-definitions.xml b/samples/certification/report-certification-definitions.xml new file mode 100644 index 00000000000..d4752cd9e08 --- /dev/null +++ b/samples/certification/report-certification-definitions.xml @@ -0,0 +1,30 @@ + + + + + Certification definitions + true + + html + From 920e454b5197c2117a3783c2668510545c5703d4 Mon Sep 17 00:00:00 2001 From: honchar Date: Mon, 14 Dec 2015 10:09:40 +0100 Subject: [PATCH 101/116] fixing problem on links panel on self dashboard page --- .../midpoint/web/page/self/component/LinksPanel.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java index 1d7af85c7a0..c7a875bb9af 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/LinksPanel.java @@ -71,11 +71,13 @@ protected void initLayout() { int currentColumn = 0; RepeatingView columnView = null; WebMarkupContainer row = null; + boolean isRowAdded = false; for (int i = 0; i < linksListSize; i++) { final RichHyperlinkType link = linksList.get(i); if (WebMiscUtil.isAuthorized(link.getAuthorization())) { if (currentColumn == 0) { row = new WebMarkupContainer(rowView.newChildId()); + isRowAdded = false; columnView = new RepeatingView(ID_LINKS_COLUMN); } WebMarkupContainer column = new WebMarkupContainer(columnView.newChildId()); @@ -132,10 +134,11 @@ public String getObject() { column.add(linkItem); columnView.add(column); - if (currentColumn == 1 || (i == (linksListSize - 1))) { + if (currentColumn == 1 || (linksList.indexOf(link) == linksListSize - 1)) { row.add(columnView); rowView.add(row); currentColumn = 0; + isRowAdded = true; } else { currentColumn++; } @@ -143,6 +146,10 @@ public String getObject() { LOGGER.trace("Link {} not authorized, skipping", link); } } + if (row != null && columnView != null && !isRowAdded){ + row.add(columnView); + rowView.add(row); + } } add(rowView); } From d21228db6cc824357f10a32f7c71a0de23a0e48b Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 14 Dec 2015 18:31:17 +0100 Subject: [PATCH 102/116] Moving things here and there in an attempt to fix association editor. Work in progress. --- .../assignment/ACAttributePanel.java | 4 +- .../assignment/ResourceListPanel.java | 4 +- .../web/component/menu/UserMenuPanel.java | 41 ++++--- .../web/component/prism/ContainerWrapper.java | 94 +++++++++++---- .../web/component/prism/ItemWrapper.java | 4 + .../web/component/prism/ObjectWrapper.java | 22 ++-- .../web/component/prism/PrismObjectPanel.java | 2 +- .../web/component/prism/PrismValuePanel.java | 84 +++++++++----- .../web/component/prism/PropertyWrapper.java | 31 +++-- .../web/component/prism/ReferenceWrapper.java | 9 +- .../component/util/BaseDeprecatedPanel.java | 79 +++++++++++++ .../component/util/BasePageAwarePanel.java | 41 +++++++ .../web/component/util/BasePanel.java | 72 ++++++++---- .../web/component/util/BaseSimplePanel.java | 78 +------------ .../web/page/admin/BaseFocusPanel.java | 4 +- .../web/page/admin/PageAdminFocus.java | 97 +++++++++------- .../AbstractAssignableSelectionPanel.java | 4 +- .../AssociationValueChoosePanel.java | 19 ++- .../component/ResourcesSelectionPanel.java | 4 +- .../midpoint/web/page/error/PageError.html | 31 +++-- .../midpoint/web/page/error/PageError.java | 30 ++++- .../web/security/MidPointApplication.java | 109 +++++++++++++++++- .../midpoint/web/security/SecurityUtils.java | 6 +- .../util/MidPointProfilingServletFilter.java | 20 +++- .../midpoint/web/util/WebMiscUtil.java | 13 +++ .../midpoint/web/ObjectWrapperTest.java | 2 +- 26 files changed, 634 insertions(+), 270 deletions(-) create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseDeprecatedPanel.java create mode 100644 gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePageAwarePanel.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ACAttributePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ACAttributePanel.java index e3eb0faed43..65e4a65e8a8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ACAttributePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ACAttributePanel.java @@ -18,7 +18,7 @@ import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.web.component.util.BasePanel; +import com.evolveum.midpoint.web.component.util.BaseDeprecatedPanel; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; @@ -33,7 +33,7 @@ /** * @author lazyman */ -public class ACAttributePanel extends BasePanel { +public class ACAttributePanel extends BaseDeprecatedPanel { private static final String ID_ATTRIBUTE_LABEL = "attributeLabel"; private static final String ID_VALUES = "values"; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ResourceListPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ResourceListPanel.java index 8c460ab7edd..dca82a76af6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ResourceListPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ResourceListPanel.java @@ -19,7 +19,7 @@ import com.evolveum.midpoint.web.component.data.ObjectDataProvider; import com.evolveum.midpoint.web.component.data.TablePanel; import com.evolveum.midpoint.web.component.data.column.LinkColumn; -import com.evolveum.midpoint.web.component.util.BasePanel; +import com.evolveum.midpoint.web.component.util.BaseDeprecatedPanel; import com.evolveum.midpoint.web.component.util.SelectableBean; import com.evolveum.midpoint.web.page.PageBase; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; @@ -34,7 +34,7 @@ /** * @author lazyman */ -public class ResourceListPanel extends BasePanel { +public class ResourceListPanel extends BaseDeprecatedPanel { public ResourceListPanel(String id) { super(id, null); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/UserMenuPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/UserMenuPanel.java index c68bcec4c75..b06432d2d0b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/UserMenuPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/UserMenuPanel.java @@ -29,6 +29,7 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.AjaxButton; +import com.evolveum.midpoint.web.component.util.BasePageAwarePanel; import com.evolveum.midpoint.web.component.util.BaseSimplePanel; import com.evolveum.midpoint.web.component.util.LoadableModel; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; @@ -40,6 +41,7 @@ import com.evolveum.midpoint.web.security.SecurityUtils; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + import org.apache.wicket.AttributeModifier; import org.apache.wicket.Page; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -103,7 +105,7 @@ public UserMenuPanel(String id) { @Override protected PasswordQuestionsDto load() { - return loadModel(); + return loadModel(null); } }; isPasswordModelLoaded = true; @@ -122,7 +124,7 @@ protected List load() { @Override protected void initLayout() { if (userModel != null && userModel.getObject() == null){ - loadModel(); + loadModel(null); } WebMarkupContainer iconBox = new WebMarkupContainer(ID_ICON_BOX); add(iconBox); @@ -142,7 +144,7 @@ public AbstractResource getObject() { @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ - loadModel(); + loadModel(null); } return jpegPhoto != null; } @@ -154,7 +156,7 @@ public boolean isVisible(){ @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ - loadModel(); + loadModel(null); } return jpegPhoto == null; @@ -191,7 +193,7 @@ public AbstractResource getObject() { @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ - loadModel(); + loadModel(null); } return jpegPhoto != null; } @@ -203,7 +205,7 @@ public boolean isVisible(){ @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ - loadModel(); + loadModel(null); } return jpegPhoto == null; } @@ -237,10 +239,6 @@ public void onClick(AjaxRequestTarget target) { }; add(editPasswordQ); - if (!isUserModelLoaded) { - loadModel(); - - } if (!isPasswordModelLoaded ){ passwordQuestionsDtoIModel = new LoadableModel(false) { @@ -248,7 +246,7 @@ public void onClick(AjaxRequestTarget target) { @Override protected PasswordQuestionsDto load() { - return loadModel(); + return loadModel(null); } }; isPasswordModelLoaded = true; @@ -287,21 +285,30 @@ private String getShortUserName() { return principal.toString(); } - private PasswordQuestionsDto loadModel() { + private PasswordQuestionsDto loadModel(PageBase parentPage) { LOGGER.trace("Loading user for Security Question Page."); PasswordQuestionsDto dto =new PasswordQuestionsDto(); OperationResult result = new OperationResult(OPERATION_LOAD_USER); - try{ - + + if (parentPage == null) { + parentPage = ((PageBase)getPage()); + } + + try { - String userOid = SecurityUtils.getPrincipalUser().getOid(); - Task task = ((PageBase)getPage()).createSimpleTask(OPERATION_LOAD_USER); + MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); + if (principal == null) { + result.recordNotApplicableIfUnknown(); + return null; + } + String userOid = principal.getOid(); + Task task = parentPage.createSimpleTask(OPERATION_LOAD_USER); OperationResult subResult = result.createSubresult(OPERATION_LOAD_USER); Collection options = SelectorOptions.createCollection(UserType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); - PrismObject user = ((PageBase)getPage()).getModelService().getObject(UserType.class, userOid, options, task, subResult); + PrismObject user = parentPage.getModelService().getObject(UserType.class, userOid, options, task, subResult); userModel.setObject(user); jpegPhoto = user == null ? null : (user.asObjectable() == null ? null : user.asObjectable().getJpegPhoto()); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java index 1bf7eee55a4..e65258093e0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java @@ -22,7 +22,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; @@ -30,6 +34,7 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.schema.constants.SchemaConstants; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; @@ -40,6 +45,7 @@ import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -54,6 +60,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; @@ -73,7 +80,7 @@ public class ContainerWrapper implements ItemWrapper, private static final String CREATE_PROPERTIES = DOT_CLASS + "createProperties"; private String displayName; - private ObjectWrapper object; + private ObjectWrapper objectWrapper; private T container; private ContainerStatus status; @@ -87,23 +94,35 @@ public class ContainerWrapper implements ItemWrapper, private OperationResult result; private PrismContainerDefinition containerDefinition; - - public ContainerWrapper(ObjectWrapper object, T container, ContainerStatus status, ItemPath path, + + public ContainerWrapper(ObjectWrapper objectWrapper, T container, ContainerStatus status, ItemPath path, PageBase pageBase) { + this(objectWrapper, container, status, path, true, pageBase); + } + + private ContainerWrapper(ObjectWrapper objectWrapper, T container, ContainerStatus status, ItemPath path, + boolean createProperties, PageBase pageBase) { Validate.notNull(container, "Prism object must not be null."); Validate.notNull(status, "Container status must not be null."); Validate.notNull(pageBase, "pageBase must not be null."); - this.object = object; + this.objectWrapper = objectWrapper; this.container = container; this.status = status; this.path = path; main = path == null; - readonly = object.isReadonly(); // [pm] this is quite questionable - showInheritedObjectAttributes = object.isShowInheritedObjectAttributes(); + readonly = objectWrapper.isReadonly(); // [pm] this is quite questionable + showInheritedObjectAttributes = objectWrapper.isShowInheritedObjectAttributes(); // have to be after setting "main" property containerDefinition = getItemDefinition(); - properties = createProperties(pageBase); + if (createProperties) { + // HACK HACK HACK, the container wrapper should not parse itself. This code should not be here. + // Constructor should NOT parse the object + // the createProperties parameter is here to avoid looping when parsing associations + properties = createProperties(pageBase); + } else { + properties = new ArrayList<>(); + } } public void revive(PrismContext prismContext) throws SchemaException { @@ -123,9 +142,9 @@ public void revive(PrismContext prismContext) throws SchemaException { @Override public PrismContainerDefinition getItemDefinition() { if (main) { - return object.getDefinition(); + return objectWrapper.getDefinition(); } else { - return object.getDefinition().findContainerDefinition(path); + return objectWrapper.getDefinition().findContainerDefinition(path); } } @@ -138,7 +157,7 @@ void clearResult() { } ObjectWrapper getObject() { - return object; + return objectWrapper; } ContainerStatus getStatus() { @@ -180,7 +199,7 @@ private List createProperties(PageBase pageBase) { if (ShadowType.F_ATTRIBUTES.equals(name)) { try { - definition = object.getRefinedAttributeDefinition(); + definition = objectWrapper.getRefinedAttributeDefinition(); if (definition == null) { PrismReference resourceRef = parent.findReference(ShadowType.F_RESOURCE_REF); @@ -188,7 +207,7 @@ private List createProperties(PageBase pageBase) { definition = pageBase .getModelInteractionService() - .getEditObjectClassDefinition((PrismObject) object.getObject(), resource, + .getEditObjectClassDefinition((PrismObject) objectWrapper.getObject(), resource, AuthorizationPhaseType.REQUEST) .toResourceAttributeContainerDefinition(); @@ -266,12 +285,31 @@ private List createProperties(PageBase pageBase) { } } else if (isShadowAssociation()) { - if (object.getAssociations() != null) { - for (PrismProperty property : object.getAssociations()) { - // TODO: fix this -> for now, read only is supported.. - PropertyWrapper propertyWrapper = new PropertyWrapper(this, property, false, - ValueStatus.NOT_CHANGED); - properties.add(propertyWrapper); + if (objectWrapper.getAssociations() != null) { + Map> assocMap = new HashMap<>(); + for (PrismContainerValue cval : objectWrapper.getAssociations()) { + ShadowAssociationType associationType = cval.asContainerable(); + QName assocName = associationType.getName(); + PrismContainer fractionalContainer = assocMap.get(assocName); + if (fractionalContainer == null) { + fractionalContainer = new PrismContainer<>(ShadowType.F_ASSOCIATION, ShadowAssociationType.class, cval.getPrismContext()); + fractionalContainer.setDefinition(cval.getParent().getDefinition()); + // HACK: set the name of the association as the element name so wrapper.getName() will return correct data. + fractionalContainer.setElementName(assocName); + assocMap.put(assocName, fractionalContainer); + } + try { + fractionalContainer.add(cval.clone()); + } catch (SchemaException e) { + // Should not happen + throw new SystemException("Unexpected error: "+e.getMessage(),e); + } + } + + for (Entry> assocEntry: assocMap.entrySet()) { + // HACK HACK HACK, the container wrapper should not parse itself. This code should not be here. + PropertyWrapper assocWrapper = new PropertyWrapper(this, assocEntry.getValue(), this.isReadonly(), ValueStatus.NOT_CHANGED); + properties.add(assocWrapper); } } @@ -311,7 +349,7 @@ private List createProperties(PageBase pageBase) { // decision is based on parent object status, not this // container's one (because container can be added also // to an existing object) - if (object.getStatus() == ContainerStatus.MODIFYING) { + if (objectWrapper.getStatus() == ContainerStatus.MODIFYING) { propertyIsReadOnly = !def.canModify(); } else { @@ -336,7 +374,7 @@ private List createProperties(PageBase pageBase) { // decision is based on parent object status, not this // container's one (because container can be added also // to an existing object) - if (object.getStatus() == ContainerStatus.MODIFYING) { + if (objectWrapper.getStatus() == ContainerStatus.MODIFYING) { propertyIsReadOnly = !def.canModify(); } else { @@ -487,7 +525,7 @@ boolean isItemVisible(ItemWrapper item) { // we decide not according to status of this container, but according to // the status of the whole object - if (object.getStatus() == ContainerStatus.ADDING) { + if (objectWrapper.getStatus() == ContainerStatus.ADDING) { return def.canAdd(); } @@ -506,8 +544,13 @@ boolean isItemVisible(ItemWrapper item) { private boolean showEmpty(ItemWrapper item) { ObjectWrapper object = getObject(); List values = item.getValues(); - boolean isEmpty = values.isEmpty(); - if (values.size() == 1) { + boolean isEmpty; + if (values == null) { + isEmpty = true; + } else { + isEmpty = values.isEmpty(); + } + if (!isEmpty && values.size() == 1) { ValueWrapper value = values.get(0); if (ValueStatus.ADDED.equals(value.getStatus())) { isEmpty = true; @@ -529,6 +572,11 @@ public void setDisplayName(String name) { this.displayName = name; } + @Override + public QName getName() { + return getItem().getElementName(); + } + public boolean isMain() { return main; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java index 21710f70af1..70d055d0a85 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapper.java @@ -18,6 +18,8 @@ import java.util.List; +import javax.xml.namespace.QName; + import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Revivable; @@ -28,6 +30,8 @@ */ public interface ItemWrapper extends Revivable, DebugDumpable { + QName getName(); + String getDisplayName(); void setDisplayName(String name); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java index d978f5a2e7b..e816dccf256 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapper.java @@ -28,6 +28,7 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.delta.*; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; @@ -123,7 +124,7 @@ public class ObjectWrapper implements Serializable, Reviva private OperationResult result; private boolean protectedAccount; - private List associations; + private List> associations; private Collection> parentOrgs = new ArrayList<>(); private OperationResult fetchResult; @@ -178,11 +179,11 @@ public void revive(PrismContext prismContext) throws SchemaException { } } - public List getAssociations() { + public List> getAssociations() { return associations; } - public void setAssociations(List associations) { + public void setAssociations(List> associations) { this.associations = associations; } @@ -625,7 +626,7 @@ public ObjectDelta getObjectDelta() throws SchemaException { ItemPath path = containerWrapper.getPath() != null ? containerWrapper.getPath() : new ItemPath(); if (itemWrapper instanceof PropertyWrapper) { - PropertyDelta pDelta = computePropertyDeltas((PropertyWrapper) itemWrapper, path); + ItemDelta pDelta = computePropertyDeltas((PropertyWrapper) itemWrapper, path); if (!pDelta.isEmpty()) { delta.addModification(pDelta); } @@ -647,14 +648,15 @@ public ObjectDelta getObjectDelta() throws SchemaException { return delta; } - private PropertyDelta computePropertyDeltas(PropertyWrapper propertyWrapper, ItemPath path) { - PrismPropertyDefinition propertyDef = propertyWrapper.getItem().getDefinition(); + private ItemDelta computePropertyDeltas(PropertyWrapper propertyWrapper, ItemPath path) { + ItemDefinition itemDef = propertyWrapper.getItem().getDefinition(); - PropertyDelta pDelta = new PropertyDelta(path, propertyDef.getName(), propertyDef, - propertyDef.getPrismContext()); // hoping the - // prismContext is there + ItemDelta pDelta = itemDef.createEmptyDelta(path); +// PropertyDelta pDelta = new PropertyDelta(path, itemDef.getName(), itemDef, +// itemDef.getPrismContext()); // hoping the +// // prismContext is there - addItemDelta(propertyWrapper, pDelta, propertyDef, path); + addItemDelta(propertyWrapper, pDelta, itemDef, path); return pDelta; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismObjectPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismObjectPanel.java index 62f6b078033..307e4b8e873 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismObjectPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismObjectPanel.java @@ -150,7 +150,7 @@ public boolean isDisabled(ObjectWrapper wrapper) { if (enabledProperty == null || enabledProperty.getValues().isEmpty()) { return false; } - ValueWrapper value = enabledProperty.getValues().get(0); + ValueWrapper value = (ValueWrapper) enabledProperty.getValues().get(0); if (value.getValue() == null) { return false; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index 0627b67def9..494f6a41cc6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum + * Copyright (c) 2010-2015 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,10 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; +import com.evolveum.midpoint.common.refinery.CompositeRefinedObjectClassDefinition; +import com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition; +import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.query.*; import com.evolveum.midpoint.util.logging.LoggingUtils; @@ -33,6 +37,7 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.page.admin.users.component.AssociationValueChoosePanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.Validate; import org.apache.wicket.AttributeModifier; @@ -63,12 +68,14 @@ import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttribute; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.web.component.form.ValueChoosePanel; import com.evolveum.midpoint.web.component.input.AutoCompleteTextPanel; import com.evolveum.midpoint.web.component.input.DatePanel; @@ -370,6 +377,9 @@ protected void onUpdate(AjaxRequestTarget target) { // } } } + if (component == null) { + throw new RuntimeException("Cannot create input component for item "+property+" ("+valueWrapper+") in "+objectWrapper); + } return component; } @@ -402,36 +412,13 @@ private Panel createTypedInputComponent(String id) { final Item item = model.getObject().getItem().getItem(); Panel panel = null; - if (item instanceof PrismProperty){ + if (item instanceof PrismProperty) { final PrismProperty property = (PrismProperty) item; PrismPropertyDefinition definition = property.getDefinition(); QName valueType = definition.getTypeName(); final String baseExpression = "value.value"; //pointing to prism property real value - ItemWrapper itemWrapper = model.getObject().getItem(); - ContainerWrapper containerWrapper = itemWrapper.getContainer(); - if(containerWrapper != null && containerWrapper.getPath() != null){ - if(ShadowType.F_ASSOCIATION.getLocalPart().equals(containerWrapper.getPath().toString())){ - PrismContext prismContext = item.getPrismContext(); - if (prismContext == null) { - prismContext = pageBase.getPrismContext(); - } - - PrismContainerValue assocContainer = (PrismContainerValue)item.getParent(); - PrismProperty objectClassItem = (PrismProperty)assocContainer.findItem(ShadowType.F_OBJECT_CLASS); - PrismProperty kindItem = (PrismProperty)assocContainer.findItem(ShadowType.F_KIND); - PrismProperty intentItem = (PrismProperty)assocContainer.findItem(ShadowType.F_INTENT); - PrismObject resource = ((ShadowType)containerWrapper.getObject().getObject().asObjectable()).getResource().asPrismObject(); - ObjectQuery query = getAssociationsSearchQuery(prismContext, resource, - objectClassItem, kindItem, intentItem); - - PropertyModel propertyModel = new PropertyModel<>(model, "value"); - List values = item.getValues(); - return new AssociationValueChoosePanel(id, model, values, false, ShadowType.class, query); - } - } - //fixing MID-1230, will be improved with some kind of annotation or something like that //now it works only in description if (ObjectType.F_DESCRIPTION.equals(definition.getName())) { @@ -621,7 +608,7 @@ public void checkInputValue(AutoCompleteTextField input, AjaxRequestTarget targe panel = new TextPanel<>(id, new PropertyModel(model, baseExpression), type); } } - } else if (item instanceof PrismReference){ + } else if (item instanceof PrismReference) { // ((PrismReferenceDefinition) item.getDefinition()). Class typeFromName = null; PrismContext prismContext = item.getPrismContext(); @@ -635,7 +622,40 @@ public void checkInputValue(AutoCompleteTextField input, AjaxRequestTarget targe final Class typeClass = typeFromName != null ? typeFromName : (item.getDefinition().getTypeClassIfKnown() != null ? item.getDefinition().getTypeClassIfKnown() : FocusType.class); panel = new ValueChoosePanel(id, new PropertyModel<>(model, "value"), item.getValues(), false, typeClass); - } + + } else if (item instanceof PrismContainer) { + ItemWrapper itemWrapper = model.getObject().getItem(); + final PrismContainer container = (PrismContainer) item; + PrismContainerDefinition definition = container.getDefinition(); + QName valueType = definition.getTypeName(); + + if (ShadowAssociationType.COMPLEX_TYPE.equals(valueType)) { + + PrismContext prismContext = item.getPrismContext(); + if (prismContext == null) { + prismContext = pageBase.getPrismContext(); + } + + ShadowType shadowType = ((ShadowType)itemWrapper.getContainer().getObject().getObject().asObjectable()); + PrismObject resource = shadowType.getResource().asPrismObject(); + RefinedResourceSchema refinedSchema; + CompositeRefinedObjectClassDefinition rOcDef; + try { + refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + rOcDef = refinedSchema.determineCompositeObjectClassDefinition(shadowType.asPrismObject()); + } catch (SchemaException e) { + throw new SystemException(e.getMessage(),e); + } + RefinedAssociationDefinition assocDef = rOcDef.findAssociation(itemWrapper.getName()); + RefinedObjectClassDefinition assocTarget = assocDef.getAssociationTarget(); + + ObjectQuery query = getAssociationsSearchQuery(prismContext, resource, + assocTarget.getTypeName(), assocTarget.getKind(), assocTarget.getIntent()); + + List values = item.getValues(); + return new AssociationValueChoosePanel(id, model, values, false, ShadowType.class, query); + } + } return panel; } @@ -792,13 +812,13 @@ private void removeValue(AjaxRequestTarget target) { target.add(parent.getParent()); } - private ObjectQuery getAssociationsSearchQuery(PrismContext prismContext, PrismObject resource, PrismProperty objectClass, PrismProperty kind, - PrismProperty intent){ + private ObjectQuery getAssociationsSearchQuery(PrismContext prismContext, PrismObject resource, QName objectClass, ShadowKindType kind, + String intent) { try { ObjectFilter andFilter = AndFilter.createAnd( - EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, objectClass.getRealValue()), - EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class, prismContext, kind.getRealValue()), -// EqualFilter.createEqual(ShadowType.F_INTENT, ShadowType.class, prismContext, intent.getRealValue()), + EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, objectClass), + EqualFilter.createEqual(ShadowType.F_KIND, ShadowType.class, prismContext, kind), +// EqualFilter.createEqual(ShadowType.F_INTENT, ShadowType.class, prismContext, intent), RefFilter.createReferenceEqual(new ItemPath(ShadowType.F_RESOURCE_REF), ShadowType.class, prismContext, resource.getOid())); ObjectQuery query = ObjectQuery.createObjectQuery(andFilter); return query; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java index f6c8cc4e612..a90c0ae62a7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PropertyWrapper.java @@ -16,12 +16,14 @@ package com.evolveum.midpoint.web.component.prism; +import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; @@ -39,20 +41,22 @@ import java.util.ArrayList; import java.util.List; +import javax.xml.namespace.QName; + /** * @author lazyman */ -public class PropertyWrapper implements ItemWrapper, Serializable, DebugDumpable { +public class PropertyWrapper implements ItemWrapper, Serializable, DebugDumpable { private ContainerWrapper container; - private PrismProperty property; + private I property; private ValueStatus status; private List values; private String displayName; private boolean readonly; - private PrismPropertyDefinition itemDefinition; + private ItemDefinition itemDefinition; - public PropertyWrapper(ContainerWrapper container, PrismProperty property, boolean readonly, ValueStatus status) { + public PropertyWrapper(ContainerWrapper container, I property, boolean readonly, ValueStatus status) { Validate.notNull(property, "Property must not be null."); Validate.notNull(status, "Property status must not be null."); @@ -82,10 +86,10 @@ public void revive(PrismContext prismContext) throws SchemaException { } @Override - public PrismPropertyDefinition getItemDefinition() { - PrismPropertyDefinition propDef = null; + public ItemDefinition getItemDefinition() { + ItemDefinition propDef = null; if (container.getItemDefinition() != null){ - propDef = container.getItemDefinition().findPropertyDefinition(property.getDefinition().getName()); + propDef = container.getItemDefinition().findItemDefinition(property.getDefinition().getName()); } if (propDef == null) { propDef = property.getDefinition(); @@ -114,8 +118,13 @@ public String getDisplayName() { } return ContainerWrapper.getDisplayNameFromItem(property); } - + @Override + public QName getName() { + return getItem().getElementName(); + } + + @Override public void setDisplayName(String displayName) { this.displayName = displayName; } @@ -133,14 +142,14 @@ public List getValues() { } @Override - public PrismProperty getItem() { + public I getItem() { return property; } private List createValues() { List values = new ArrayList(); - for (PrismPropertyValue prismValue : (List) property.getValues()) { + for (PrismValue prismValue : (List) property.getValues()) { values.add(new ValueWrapper(this, prismValue, ValueStatus.NOT_CHANGED)); } @@ -161,7 +170,7 @@ public void addValue(){ } public ValueWrapper createAddedValue() { - PrismPropertyDefinition definition = property.getDefinition(); + ItemDefinition definition = property.getDefinition(); ValueWrapper wrapper; if (SchemaConstants.T_POLY_STRING_TYPE.equals(definition.getTypeName())) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java index b78ede47502..66da3420077 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ReferenceWrapper.java @@ -19,6 +19,8 @@ import java.util.ArrayList; import java.util.List; +import javax.xml.namespace.QName; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; @@ -98,8 +100,13 @@ public String getDisplayName() { public void setDisplayName(String displayName) { this.displayName = displayName; } + + @Override + public QName getName() { + return getItem().getElementName(); + } - public ValueStatus getStatus() { + public ValueStatus getStatus() { return status; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseDeprecatedPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseDeprecatedPanel.java new file mode 100644 index 00000000000..ed5ca981ab0 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseDeprecatedPanel.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010-2013 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.web.component.util; + +import com.evolveum.midpoint.web.page.PageBase; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.StringResourceModel; + +/** + * @author lazyman + */ +@Deprecated +public abstract class BaseDeprecatedPanel extends Panel { + + private IModel model; + private boolean initialized; + + public BaseDeprecatedPanel(String id, IModel model) { + super(id); + + this.model = model; + } + + @Override + protected void onBeforeRender() { + super.onBeforeRender(); + + if (initialized) { + return; + } + initLayout(); + initialized = true; + } + + protected IModel getModel() { + return model; + } + + public String getString(String resourceKey, Object... objects) { + return createStringResource(resourceKey, objects).getString(); + } + + public StringResourceModel createStringResource(String resourceKey, Object... objects) { + return new StringResourceModel(resourceKey, this, null, resourceKey, objects); + } + + public StringResourceModel createStringResource(Enum e) { + String resourceKey = e.getDeclaringClass().getSimpleName() + "." + e.name(); + return createStringResource(resourceKey); + } + + public PageBase getPageBase() { + return (PageBase) getPage(); + } + + protected void initLayout() { + } + + protected String createComponentPath(String... components) { + return StringUtils.join(components, ":"); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePageAwarePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePageAwarePanel.java new file mode 100644 index 00000000000..bfab5d7ba82 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePageAwarePanel.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.web.component.util; + +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.web.page.PageBase; + +/** + * @author semancik + */ +public class BasePageAwarePanel extends BasePanel { + + public BasePageAwarePanel(String id, PageBase parentPage) { + this(id, null, parentPage); + } + + public BasePageAwarePanel(String id, IModel model, PageBase parentPage) { + super(id, model); + + initLayout(parentPage); + } + + protected void initLayout(PageBase parentPage) { + + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePanel.java index d2531730432..b3dd40f4536 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BasePanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum + * Copyright (c) 2010-2015 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,43 +16,43 @@ package com.evolveum.midpoint.web.component.util; -import com.evolveum.midpoint.web.page.PageBase; +import com.evolveum.midpoint.web.security.MidPointApplication; +import com.evolveum.midpoint.web.security.MidPointAuthWebSession; +import com.evolveum.midpoint.web.security.WebApplicationConfiguration; import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.StringResourceModel; /** * @author lazyman + * @author semancik */ -@Deprecated -public abstract class BasePanel extends Panel { +public class BasePanel extends Panel { private IModel model; - private boolean initialized; + + public BasePanel(String id) { + this(id, null); + } public BasePanel(String id, IModel model) { super(id); - - this.model = model; + this.model = model == null ? createModel() : model; } - @Override - protected void onBeforeRender() { - super.onBeforeRender(); - - if (initialized) { - return; - } - initLayout(); - initialized = true; + public IModel createModel() { + return null; } - protected IModel getModel() { + public IModel getModel() { return model; } + public T getModelObject() { + return model != null ? model.getObject() : null; + } + public String getString(String resourceKey, Object... objects) { return createStringResource(resourceKey, objects).getString(); } @@ -62,18 +62,44 @@ public StringResourceModel createStringResource(String resourceKey, Object... ob } public StringResourceModel createStringResource(Enum e) { - String resourceKey = e.getDeclaringClass().getSimpleName() + "." + e.name(); - return createStringResource(resourceKey); + return createStringResource(e, null); } - public PageBase getPageBase() { - return (PageBase) getPage(); + public StringResourceModel createStringResource(Enum e, String prefix) { + return createStringResource(e, prefix, null); } - protected void initLayout() { + public StringResourceModel createStringResource(Enum e, String prefix, String nullKey) { + StringBuilder sb = new StringBuilder(); + if (StringUtils.isNotEmpty(prefix)) { + sb.append(prefix).append('.'); + } + + if (e == null) { + if (StringUtils.isNotEmpty(nullKey)) { + sb.append(nullKey); + } else { + sb = new StringBuilder(); + } + } else { + sb.append(e.getDeclaringClass().getSimpleName()).append('.'); + sb.append(e.name()); + } + + return createStringResource(sb.toString()); } protected String createComponentPath(String... components) { return StringUtils.join(components, ":"); } + + public WebApplicationConfiguration getWebApplicationConfiguration() { + MidPointApplication application = (MidPointApplication) MidPointApplication.get(); + return application.getWebApplicationConfiguration(); + } + + @Override + public MidPointAuthWebSession getSession() { + return (MidPointAuthWebSession) super.getSession(); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseSimplePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseSimplePanel.java index 5466ddaa407..2d7da60d95d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseSimplePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/BaseSimplePanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum + * Copyright (c) 2010-2015 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,95 +16,25 @@ package com.evolveum.midpoint.web.component.util; -import com.evolveum.midpoint.web.security.MidPointApplication; -import com.evolveum.midpoint.web.security.MidPointAuthWebSession; -import com.evolveum.midpoint.web.security.WebApplicationConfiguration; -import org.apache.commons.lang.StringUtils; -import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.StringResourceModel; /** * @author lazyman + * @author semancik */ -public class BaseSimplePanel extends Panel { - - private IModel model; +public class BaseSimplePanel extends BasePanel { public BaseSimplePanel(String id) { this(id, null); } public BaseSimplePanel(String id, IModel model) { - super(id); - this.model = model == null ? createModel() : model; + super(id, model); initLayout(); } - public IModel createModel() { - return null; - } - - public IModel getModel() { - return model; - } - - public T getModelObject() { - return model != null ? model.getObject() : null; - } - - public String getString(String resourceKey, Object... objects) { - return createStringResource(resourceKey, objects).getString(); - } - - public StringResourceModel createStringResource(String resourceKey, Object... objects) { - return new StringResourceModel(resourceKey, this, null, resourceKey, objects); - } - - public StringResourceModel createStringResource(Enum e) { - return createStringResource(e, null); - } - - public StringResourceModel createStringResource(Enum e, String prefix) { - return createStringResource(e, prefix, null); - } - - public StringResourceModel createStringResource(Enum e, String prefix, String nullKey) { - StringBuilder sb = new StringBuilder(); - if (StringUtils.isNotEmpty(prefix)) { - sb.append(prefix).append('.'); - } - - if (e == null) { - if (StringUtils.isNotEmpty(nullKey)) { - sb.append(nullKey); - } else { - sb = new StringBuilder(); - } - } else { - sb.append(e.getDeclaringClass().getSimpleName()).append('.'); - sb.append(e.name()); - } - - return createStringResource(sb.toString()); - } - - protected String createComponentPath(String... components) { - return StringUtils.join(components, ":"); - } - protected void initLayout() { } - - public WebApplicationConfiguration getWebApplicationConfiguration() { - MidPointApplication application = (MidPointApplication) MidPointApplication.get(); - return application.getWebApplicationConfiguration(); - } - - @Override - public MidPointAuthWebSession getSession() { - return (MidPointAuthWebSession) super.getSession(); - } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/BaseFocusPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/BaseFocusPanel.java index 94bc032c58d..8b030813ab0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/BaseFocusPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/BaseFocusPanel.java @@ -54,6 +54,7 @@ import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.web.util.WebMiscUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + import org.apache.commons.lang.StringUtils; import org.apache.wicket.Component; import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; @@ -74,6 +75,7 @@ import org.apache.wicket.util.string.StringValue; import javax.xml.namespace.QName; + import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -722,7 +724,7 @@ private void updateShadowActivation(AjaxRequestTarget target, List> getFocusModel() { } public void initialize(final PrismObject userToEdit) { - focusModel = new LoadableModel>(false) { - - @Override - protected ObjectWrapper load() { - return loadFocusWrapper(userToEdit); - } - }; - shadowModel = new LoadableModel>(false) { - - @Override - protected List load() { - return loadShadowWrappers(); - } - }; - - orgModel = new LoadableModel>(false) { - - @Override - protected List load() { - return loadOrgWrappers(); - } - }; - - assignmentsModel = new LoadableModel>(false) { - - @Override - protected List load() { - return loadAssignments(); - } - }; - - performCustomInitialization(); - - initLayout(); + try { + + focusModel = new LoadableModel>(false) { + + @Override + protected ObjectWrapper load() { + return loadFocusWrapper(userToEdit); + } + }; + shadowModel = new LoadableModel>(false) { + + @Override + protected List load() { + return loadShadowWrappers(); + } + }; + + orgModel = new LoadableModel>(false) { + + @Override + protected List load() { + return loadOrgWrappers(); + } + }; + + assignmentsModel = new LoadableModel>(false) { + + @Override + protected List load() { + return loadAssignments(); + } + }; + + performCustomInitialization(); + + initLayout(); + + LOGGER.trace("Page {} initialized", this); + } catch (Exception e) { + LoggingUtils.logException(LOGGER, "Error initializing page "+this, e); + } } protected void performCustomInitialization() { @@ -681,9 +691,9 @@ private

List loadProjectionWrappers(C PrismContainer associationContainer = projection .findContainer(ShadowType.F_ASSOCIATION); if (associationContainer != null && associationContainer.getValues() != null) { - List associations = new ArrayList<>( + List> associations = new ArrayList<>( associationContainer.getValues().size()); - for (PrismContainerValue associationVal : associationContainer.getValues()) { + for (PrismContainerValue associationVal : associationContainer.getValues()) { ShadowAssociationType associationType = (ShadowAssociationType) associationVal .asContainerable(); ObjectReferenceType shadowRef = associationType.getShadowRef(); @@ -691,12 +701,11 @@ private

List loadProjectionWrappers(C // associations we can safely eliminate fetching // from resource, because we need only the name if (shadowRef != null) { - PrismObject association = getModelService() - .getObject(ShadowType.class, shadowRef.getOid(), - SelectorOptions.createCollection( - GetOperationOptions.createNoFetch()), - task, subResult); - associations.add(association.findProperty(ShadowType.F_NAME)); + PrismObject associationTargetShadow = getModelService().getObject(ShadowType.class, + shadowRef.getOid(), SelectorOptions.createCollection(GetOperationOptions.createNoFetch()), + task, subResult); + shadowRef.asReferenceValue().setObject(associationTargetShadow); + associations.add(associationVal); } } wrapper.setAssociations(associations); @@ -1704,7 +1713,7 @@ private void updateShadowActivation(AjaxRequestTarget target, List extends BasePanel { +public abstract class AbstractAssignableSelectionPanel extends BaseDeprecatedPanel { private static final String ID_ADD = "add"; protected Class type = (Class) RoleType.class; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java index cdfde587186..40d3798bc01 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoosePanel.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.evolveum.midpoint.web.page.admin.users.component; import com.evolveum.midpoint.prism.*; @@ -57,11 +72,9 @@ public class AssociationValueChoosePanel extends Simpl private static final String ID_REMOVE = "remove"; private static final String ID_BUTTON_GROUP = "buttonGroup"; private static final String ID_EDIT = "edit"; - private IModel model; - protected static final String MODAL_ID_OBJECT_SELECTION_POPUP = "objectSelectionPopup"; - + private IModel model; private ObjectQuery query = null; public AssociationValueChoosePanel(String id, IModel model, List values, boolean required, Class type, diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/ResourcesSelectionPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/ResourcesSelectionPanel.java index 6771307fc88..d3012e9adbd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/ResourcesSelectionPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/ResourcesSelectionPanel.java @@ -28,7 +28,7 @@ import com.evolveum.midpoint.web.component.assignment.AssignmentSearchDto; import com.evolveum.midpoint.web.component.data.TablePanel; import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn; -import com.evolveum.midpoint.web.component.util.BasePanel; +import com.evolveum.midpoint.web.component.util.BaseDeprecatedPanel; import com.evolveum.midpoint.web.component.util.LoadableModel; import com.evolveum.midpoint.web.component.util.SelectableBean; import com.evolveum.midpoint.web.page.PageBase; @@ -51,7 +51,7 @@ import java.util.ArrayList; import java.util.List; -public class ResourcesSelectionPanel extends BasePanel { +public class ResourcesSelectionPanel extends BaseDeprecatedPanel { private static final String ID_BASIC_SEARCH = "basicSearch"; private static final String ID_SEARCH_FORM = "searchForm"; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/error/PageError.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/error/PageError.html index 2fde0f00a75..7f8898e7517 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/error/PageError.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/error/PageError.html @@ -1,6 +1,6 @@