From 6ec41e3ed882171d2d41613fc888f77ed9b0ef1e Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 2 May 2016 21:19:22 +0200 Subject: [PATCH 01/12] Evolveum example: OpenLDAP resource, org object template, metaroles --- samples/evolveum/object-template-org.xml | 73 ++++ samples/evolveum/org-users.xml | 36 ++ samples/evolveum/resource-openldap.xml | 454 ++++++++++++++++++++++ samples/evolveum/role-meta-functional.xml | 77 ++++ samples/evolveum/role-meta-project.xml | 141 +++++++ 5 files changed, 781 insertions(+) create mode 100644 samples/evolveum/object-template-org.xml create mode 100644 samples/evolveum/resource-openldap.xml create mode 100644 samples/evolveum/role-meta-functional.xml create mode 100644 samples/evolveum/role-meta-project.xml diff --git a/samples/evolveum/object-template-org.xml b/samples/evolveum/object-template-org.xml new file mode 100644 index 00000000000..e47a3fd553b --- /dev/null +++ b/samples/evolveum/object-template-org.xml @@ -0,0 +1,73 @@ + + + + + + Org Template + + + template-org-meta-project + strong + + orgType + + + + + + + + + assignment + + + + + + + + template-org-meta-functional + strong + + orgType + + + + + + + + + assignment + + + + + + + diff --git a/samples/evolveum/org-users.xml b/samples/evolveum/org-users.xml index a20d5173cff..258006d677c 100644 --- a/samples/evolveum/org-users.xml +++ b/samples/evolveum/org-users.xml @@ -35,6 +35,9 @@ F1100 Software development, research, technologies. + + + Research and Development Division 1100 functional @@ -45,6 +48,9 @@ F1110 Software development and research + + + Development Section 1110 functional @@ -55,6 +61,9 @@ F1120 Testing and quality assurance + + + QA Section 1120 functional @@ -65,6 +74,9 @@ F1130 Support and professional services + + + Services Section 1130 functional @@ -74,6 +86,9 @@ F1200 + + + Business Division 1200 functional @@ -84,6 +99,9 @@ F1210 Marketing and PR + + + Marketing Section 1210 functional @@ -94,6 +112,9 @@ F1220 Accounting, bookkeeping and HR + + + Accounting Section 1220 functional @@ -112,6 +133,9 @@ P0001 + + + midPoint 0001 project @@ -120,6 +144,9 @@ P0002 + + + ConnId 0002 project @@ -128,6 +155,9 @@ P0003 + + + LDAP Connector 0003 project @@ -136,6 +166,9 @@ P0004 + + + OpenStack Integration 0004 project @@ -144,6 +177,9 @@ P0005 + + + Website 0005 project diff --git a/samples/evolveum/resource-openldap.xml b/samples/evolveum/resource-openldap.xml new file mode 100644 index 00000000000..124734c706a --- /dev/null +++ b/samples/evolveum/resource-openldap.xml @@ -0,0 +1,454 @@ + + + + + + + + + OpenLDAP + + + LDAP resource using a ConnId LDAP connector. It contains configuration + for use with OpenLDAP servers. + + + + + Reference to the OpenICF LDAP connector. This is dynamic reference, it will be + translated to OID during import. + + + + c:connectorType + com.evolveum.polygon.connector.ldap.LdapConnector + + + + + + + 389 + localhost + dc=example,dc=com + cn=idm,ou=Administrators,dc=example,dc=com + + secret + + auto + SSHA + uid,cn,ou,dc + 2.5.13.3 + memberOf + createTimestamp + always + + + false + false + false + + + + + + account + Normal Account + true + ri:inetOrgPerson + + ri:dn + Distinguished Name + + 0 + + true + true + true + + + + + $user/name + + + + + + + + ri:entryUUID + Entry UUID + + + true + false + true + + + + + ri:cn + Common Name + + 0 + + true + true + true + + + + + + fullName + + + + + fullName + + + + + ri:sn + Surname + + 0 + + + + familyName + + + + + familyName + + + + + ri:givenName + Given Name + + + givenName + + + + + givenName + + + + + ri:uid + Login Name + + weak + + name + + + + + + + + name + + + + + ri:description + + weak + + Created by midPoint + + + + + ri:l + Location + + + locality + + + + + ri:employeeType + Employee Type + false + + + employeeType + + + + + + ri:ldapGroup + LDAP Group Membership + entitlement + ldapGroup + objectToSubject + ri:member + ri:dn + + + + ri:posixGroup + POSIX Group Membership + entitlement + posixGroup + objectToSubject + ri:memberUid + ri:uid + + + + 5 + + + + + + http://prism.evolveum.com/xml/ns/public/matching-rule-3#stringIgnoreCase + attributes/ri:dn + cn=idm,ou=Administrators,dc=example,dc=com + + + + + + + + + weak + + + + + + + + + + + + + + + + weak + + + + + + + + + + + entitlement + ldapGroup + LDAP Group + ri:groupOfNames + + ri:organizationalUnit + + + attributes/dn + ou=groups,dc=example,dc=com + + + + + + ri:dn + + + name + + + + + + + + ri:member + minimal + + weak + + cn=fake,dc=example,dc=com + + + + + ri:cn + + weak + + name + + + + + + ri:cn + + + + + + entitlement + posixGroup + POSIX Group + ri:posixGroup + + ri:organizationalUnit + + + attributes/dn + ou=posixgroups,dc=example,dc=com + + + + + + ri:dn + + + name + + + + + + + + ri:cn + + weak + + name + + + + + + ri:cn + + + + + + + + + + true + + + + Correlation expression is a search query. + Following search queury will look for users that have "name" + equal to the "uid" attribute of the account. Simply speaking, + it will look for match in usernames in the IDM and the resource. + The correlation rule always looks for users, so it will not match + any other object type. + + + name + + + declare namespace + ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"; + $account/attributes/ri:uid + + + + + + + + linked + true + + + deleted + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink + + + + + + unlinked + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#link + + + + + unmatched + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus + + + + + + + + diff --git a/samples/evolveum/role-meta-functional.xml b/samples/evolveum/role-meta-functional.xml new file mode 100644 index 00000000000..2ae19e0b358 --- /dev/null +++ b/samples/evolveum/role-meta-functional.xml @@ -0,0 +1,77 @@ + + + + + Functional Org Metarole + + + + + + entitlement + ldapGroup + + ri:description + + strong + + displayName + + + + + + + + FM-I2 + + FM-I2 + + account + default + + ri:ldapGroup + + + + + entitlement + ldapGroup + + + + + + + 2 + + + + + + + + diff --git a/samples/evolveum/role-meta-project.xml b/samples/evolveum/role-meta-project.xml new file mode 100644 index 00000000000..0652cd74d8e --- /dev/null +++ b/samples/evolveum/role-meta-project.xml @@ -0,0 +1,141 @@ + + + + + Project Metarole + + + + + + entitlement + ldapGroup + + ri:description + + strong + + displayName + + + + + + + + PM-I2-L + + PM-I2-L + + account + default + + ri:ldapGroup + + + + + entitlement + ldapGroup + + + + + + + 2 + + + + + + + + + + + + entitlement + posixGroup + + ri:description + + strong + + displayName + + + + + ri:gidNumber + + + identifier + + + + + + + + + + + PM-I2-P + + PM-I2-P + + account + default + + ri:posixGroup + + + + + entitlement + posixGroup + + + + + + + 2 + + + + + + + + From 03d39d4bfe091c5939988d89d12358656a26ea31 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 3 May 2016 12:19:42 +0200 Subject: [PATCH 02/12] LDAP files for the Evolveum sample --- samples/evolveum/posixgroups.aci | 1 + samples/evolveum/posixgroups.ldif | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 samples/evolveum/posixgroups.aci create mode 100644 samples/evolveum/posixgroups.ldif diff --git a/samples/evolveum/posixgroups.aci b/samples/evolveum/posixgroups.aci new file mode 100644 index 00000000000..e6a2fd90f9f --- /dev/null +++ b/samples/evolveum/posixgroups.aci @@ -0,0 +1 @@ +to dn.subtree="ou=posixgroups,dc=example,dc=com" by dn="cn=idm,ou=Administrators,dc=example,dc=com" write diff --git a/samples/evolveum/posixgroups.ldif b/samples/evolveum/posixgroups.ldif new file mode 100644 index 00000000000..5fe741470ac --- /dev/null +++ b/samples/evolveum/posixgroups.ldif @@ -0,0 +1,4 @@ +dn: ou=posixgroups,dc=example,dc=com +changetype: add +objectclass: organizationalUnit +ou: posixgroups From 75138092d95e4b6fd167b36b7d23c69c7259e121 Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Tue, 3 May 2016 13:22:24 +0200 Subject: [PATCH 03/12] relation info also to the row when assigning the org and BEFORE saving. MID-2746 --- .../assignment/AssignmentEditorPanel.java | 1570 +++++++++-------- 1 file changed, 803 insertions(+), 767 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentEditorPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentEditorPanel.java index f287ae76a8b..4a1da6ed3b2 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentEditorPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentEditorPanel.java @@ -92,801 +92,837 @@ public class AssignmentEditorPanel extends BasePanel { private static final Trace LOGGER = TraceManager.getTrace(AssignmentEditorPanel.class); - private static final String DOT_CLASS = AssignmentEditorPanel.class.getName() + "."; - private static final String OPERATION_LOAD_OBJECT = DOT_CLASS + "loadObject"; - private static final String OPERATION_LOAD_RESOURCE = DOT_CLASS + "loadResource"; - private static final String OPERATION_LOAD_ATTRIBUTES = DOT_CLASS + "loadAttributes"; - - private static final String ID_HEADER_ROW = "headerRow"; - private static final String ID_SELECTED = "selected"; - private static final String ID_TYPE_IMAGE = "typeImage"; - private static final String ID_NAME_LABEL = "nameLabel"; - private static final String ID_NAME = "name"; - private static final String ID_ACTIVATION = "activation"; - private static final String ID_ACTIVATION_BLOCK = "activationBlock"; - private static final String ID_EXPAND = "expand"; - private static final String ID_BODY = "body"; - private static final String ID_DESCRIPTION = "description"; - private static final String ID_RELATION_CONTAINER = "relationContainer"; - private static final String ID_RELATION = "relation"; - private static final String ID_RELATION_LABEL = "relationLabel"; - private static final String ID_ADMINISTRATIVE_STATUS = "administrativeStatus"; - private static final String ID_VALID_FROM = "validFrom"; - private static final String ID_VALID_TO = "validTo"; - private static final String ID_SHOW_EMPTY = "showEmpty"; - private static final String ID_SHOW_EMPTY_LABEL = "showEmptyLabel"; - private static final String ID_ATTRIBUTES = "attributes"; - private static final String ID_ATTRIBUTE = "attribute"; - private static final String ID_AC_ATTRIBUTE = "acAttribute"; - private static final String ID_TARGET = "target"; - private static final String ID_TARGET_CONTAINER = "targetContainer"; - private static final String ID_CONSTRUCTION_CONTAINER = "constructionContainer"; - private static final String ID_CONTAINER_TENANT_REF = "tenantRefContainer"; - private static final String ID_TENANT_CHOOSER = "tenantRefChooser"; - private static final String ID_CONTAINER_ORG_REF = "orgRefContainer"; - private static final String ID_ORG_CHOOSER = "orgRefChooser"; - private static final String ID_BUTTON_SHOW_MORE = "errorLink"; - private static final String ID_ERROR_ICON = "errorIcon"; - - private IModel> attributesModel; - - public AssignmentEditorPanel(String id, IModel model) { - super(id, model); - - attributesModel = new LoadableModel>(false) { - @Override - protected List load() { - return loadAttributes(); - } - }; - - initLayout(); - } - - @Override - public void renderHead(IHeaderResponse response) { - super.renderHead(response); - - response.render(CssHeaderItem.forReference( - new PackageResourceReference(AssignmentEditorPanel.class, "AssignmentEditorPanel.css"))); - } - - private void initLayout() { - setOutputMarkupId(true); - WebMarkupContainer headerRow = new WebMarkupContainer(ID_HEADER_ROW); - headerRow.add(AttributeModifier.append("class", createHeaderClassModel(getModel()))); - headerRow.setOutputMarkupId(true); - add(headerRow); - - AjaxCheckBox selected = new AjaxCheckBox(ID_SELECTED, - new PropertyModel(getModel(), AssignmentEditorDto.F_SELECTED)) { - private static final long serialVersionUID = 1L; - - @Override - protected void onUpdate(AjaxRequestTarget target) { - //do we want to update something? - } - }; - headerRow.add(selected); - - WebMarkupContainer typeImage = new WebMarkupContainer(ID_TYPE_IMAGE); - typeImage.add(AttributeModifier.append("class", createImageTypeModel(getModel()))); - headerRow.add(typeImage); - - Label errorIcon = new Label(ID_ERROR_ICON); - errorIcon.add(new VisibleEnableBehaviour(){ + private static final String DOT_CLASS = AssignmentEditorPanel.class.getName() + "."; + private static final String OPERATION_LOAD_OBJECT = DOT_CLASS + "loadObject"; + private static final String OPERATION_LOAD_RESOURCE = DOT_CLASS + "loadResource"; + private static final String OPERATION_LOAD_ATTRIBUTES = DOT_CLASS + "loadAttributes"; + + private static final String ID_HEADER_ROW = "headerRow"; + private static final String ID_SELECTED = "selected"; + private static final String ID_TYPE_IMAGE = "typeImage"; + private static final String ID_NAME_LABEL = "nameLabel"; + private static final String ID_NAME = "name"; + private static final String ID_ACTIVATION = "activation"; + private static final String ID_ACTIVATION_BLOCK = "activationBlock"; + private static final String ID_EXPAND = "expand"; + private static final String ID_BODY = "body"; + private static final String ID_DESCRIPTION = "description"; + private static final String ID_RELATION_CONTAINER = "relationContainer"; + private static final String ID_RELATION = "relation"; + private static final String ID_RELATION_LABEL = "relationLabel"; + private static final String ID_ADMINISTRATIVE_STATUS = "administrativeStatus"; + private static final String ID_VALID_FROM = "validFrom"; + private static final String ID_VALID_TO = "validTo"; + private static final String ID_SHOW_EMPTY = "showEmpty"; + private static final String ID_SHOW_EMPTY_LABEL = "showEmptyLabel"; + private static final String ID_ATTRIBUTES = "attributes"; + private static final String ID_ATTRIBUTE = "attribute"; + private static final String ID_AC_ATTRIBUTE = "acAttribute"; + private static final String ID_TARGET = "target"; + private static final String ID_TARGET_CONTAINER = "targetContainer"; + private static final String ID_CONSTRUCTION_CONTAINER = "constructionContainer"; + private static final String ID_CONTAINER_TENANT_REF = "tenantRefContainer"; + private static final String ID_TENANT_CHOOSER = "tenantRefChooser"; + private static final String ID_CONTAINER_ORG_REF = "orgRefContainer"; + private static final String ID_ORG_CHOOSER = "orgRefChooser"; + private static final String ID_BUTTON_SHOW_MORE = "errorLink"; + private static final String ID_ERROR_ICON = "errorIcon"; + + private IModel> attributesModel; + + public AssignmentEditorPanel(String id, IModel model) { + super(id, model); + + attributesModel = new LoadableModel>(false) { + @Override + protected List load() { + return loadAttributes(); + } + }; + + initLayout(); + } + + @Override + public void renderHead(IHeaderResponse response) { + super.renderHead(response); + + response.render(CssHeaderItem.forReference( + new PackageResourceReference(AssignmentEditorPanel.class, "AssignmentEditorPanel.css"))); + } + + private void initLayout() { + setOutputMarkupId(true); + WebMarkupContainer headerRow = new WebMarkupContainer(ID_HEADER_ROW); + headerRow.add(AttributeModifier.append("class", createHeaderClassModel(getModel()))); + headerRow.setOutputMarkupId(true); + add(headerRow); + + AjaxCheckBox selected = new AjaxCheckBox(ID_SELECTED, + new PropertyModel(getModel(), AssignmentEditorDto.F_SELECTED)) { + private static final long serialVersionUID = 1L; + + @Override + protected void onUpdate(AjaxRequestTarget target) { + // do we want to update something? + } + }; + headerRow.add(selected); + + WebMarkupContainer typeImage = new WebMarkupContainer(ID_TYPE_IMAGE); + typeImage.add(AttributeModifier.append("class", createImageTypeModel(getModel()))); + headerRow.add(typeImage); + + Label errorIcon = new Label(ID_ERROR_ICON); + errorIcon.add(new VisibleEnableBehaviour() { + private static final long serialVersionUID = 1L; + + @Override + public boolean isVisible() { + return !isTargetValid(); + } + }); + headerRow.add(errorIcon); + + AjaxLink name = new AjaxLink(ID_NAME) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + nameClickPerformed(target); + } + }; + headerRow.add(name); + + AjaxLink errorLink = new AjaxLink(ID_BUTTON_SHOW_MORE) { private static final long serialVersionUID = 1L; @Override - public boolean isVisible() { - return !isTargetValid(); - } - }); - headerRow.add(errorIcon); - - AjaxLink name = new AjaxLink(ID_NAME) { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - nameClickPerformed(target); - } - }; - headerRow.add(name); - - AjaxLink errorLink = new AjaxLink(ID_BUTTON_SHOW_MORE) { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - showErrorPerformed(target); - } - }; - errorLink.add(new VisibleEnableBehaviour() { - private static final long serialVersionUID = 1L; - - @Override - public boolean isVisible() { - return !isTargetValid(); - } - }); - headerRow.add(errorLink); - - Label nameLabel = new Label(ID_NAME_LABEL, createAssignmentNameLabelModel()); - name.add(nameLabel); - - Label activation = new Label(ID_ACTIVATION, createActivationModel()); - headerRow.add(activation); - - ToggleIconButton expandButton = new ToggleIconButton(ID_EXPAND, - GuiStyleConstants.CLASS_ICON_EXPAND, GuiStyleConstants.CLASS_ICON_COLLAPSE) { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - nameClickPerformed(target); - } - - @Override + public void onClick(AjaxRequestTarget target) { + showErrorPerformed(target); + } + }; + errorLink.add(new VisibleEnableBehaviour() { + private static final long serialVersionUID = 1L; + + @Override + public boolean isVisible() { + return !isTargetValid(); + } + }); + headerRow.add(errorLink); + + Label nameLabel = new Label(ID_NAME_LABEL, createAssignmentNameLabelModel(false)); + nameLabel.setOutputMarkupId(true); + name.add(nameLabel); + + Label activation = new Label(ID_ACTIVATION, createActivationModel()); + headerRow.add(activation); + + ToggleIconButton expandButton = new ToggleIconButton(ID_EXPAND, GuiStyleConstants.CLASS_ICON_EXPAND, + GuiStyleConstants.CLASS_ICON_COLLAPSE) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + nameClickPerformed(target); + } + + @Override public boolean isOn() { return !AssignmentEditorPanel.this.getModelObject().isMinimized(); } - }; - headerRow.add(expandButton); + }; + headerRow.add(expandButton); - WebMarkupContainer body = new WebMarkupContainer(ID_BODY); - body.setOutputMarkupId(true); - body.add(new VisibleEnableBehaviour() { + WebMarkupContainer body = new WebMarkupContainer(ID_BODY); + body.setOutputMarkupId(true); + body.add(new VisibleEnableBehaviour() { - @Override - public boolean isVisible() { - AssignmentEditorDto editorDto = AssignmentEditorPanel.this.getModel().getObject(); - return !editorDto.isMinimized(); - } - }); - add(body); - - initBodyLayout(body); - } + @Override + public boolean isVisible() { + AssignmentEditorDto editorDto = AssignmentEditorPanel.this.getModel().getObject(); + return !editorDto.isMinimized(); + } + }); + add(body); - private IModel createAssignmentNameLabelModel(){ - return new AbstractReadOnlyModel() { + initBodyLayout(body); + } - @Override - public String getObject() { - if(getModel() != null && getModel().getObject() != null){ - AssignmentEditorDto dto = getModelObject(); + private IModel createAssignmentNameLabelModel(final boolean isManager) { + return new AbstractReadOnlyModel() { - if(dto.getName() != null){ - return dto.getName(); - } + @Override + public String getObject() { + if (getModel() != null && getModel().getObject() != null) { + AssignmentEditorDto dto = getModelObject(); + + if (dto.getName() != null) { + StringBuilder name = new StringBuilder(dto.getName()); + if (isManager) { + name.append(" - Manager"); + } + return name.toString(); + } + + if (dto.getAltName() != null) { + return getString("AssignmentEditorPanel.name.focus"); + } + } + + return getString("AssignmentEditorPanel.name.noTarget"); + } + }; + } - if(dto.getAltName() != null){ - return getString("AssignmentEditorPanel.name.focus"); - } - } + private boolean isTargetValid() { - return getString("AssignmentEditorPanel.name.noTarget"); - } - }; - } + if (getModel() != null && getModel().getObject() != null) { + AssignmentEditorDto dto = getModelObject(); - private boolean isTargetValid(){ + if (dto.getName() == null && dto.getAltName() == null) { + return false; + } + } - if(getModel() != null && getModel().getObject() != null){ - AssignmentEditorDto dto = getModelObject(); + return true; + } - if(dto.getName() == null && dto.getAltName() == null){ - return false; - } - } + private IModel createHeaderClassModel(final IModel model) { + return new AbstractReadOnlyModel() { + private static final long serialVersionUID = 1L; - return true; - } + @Override + public String getObject() { + AssignmentEditorDto dto = model.getObject(); + return dto.getStatus().name().toLowerCase(); + } + }; + } - private IModel createHeaderClassModel(final IModel model) { - return new AbstractReadOnlyModel() { + private IModel createActivationModel() { + return new AbstractReadOnlyModel() { private static final long serialVersionUID = 1L; @Override - public String getObject() { - AssignmentEditorDto dto = model.getObject(); - return dto.getStatus().name().toLowerCase(); - } - }; - } - - private IModel createActivationModel() { - return new AbstractReadOnlyModel() { - private static final long serialVersionUID = 1L; - - @Override - public String getObject() { - AssignmentEditorDto dto = getModel().getObject(); - ActivationType activation = dto.getActivation(); - if (activation == null) { - return "-"; - } - - ActivationStatusType status = activation.getAdministrativeStatus(); - String strEnabled = createStringResource(status, "lower", "ActivationStatusType.null").getString(); - - if (activation.getValidFrom() != null && activation.getValidTo() != null) { - return getString("AssignmentEditorPanel.enabledFromTo", strEnabled, - MiscUtil.asDate(activation.getValidFrom()), MiscUtil.asDate(activation.getValidTo())); - } else if (activation.getValidFrom() != null) { - return getString("AssignmentEditorPanel.enabledFrom", strEnabled, - MiscUtil.asDate(activation.getValidFrom())); - } else if (activation.getValidTo() != null) { - return getString("AssignmentEditorPanel.enabledTo", strEnabled, - MiscUtil.asDate(activation.getValidTo())); - } - - return "-"; - } - }; - } - - private IModel createDateModel(final IModel model) { - return new Model() { - - @Override - public Date getObject() { - XMLGregorianCalendar calendar = model.getObject(); - if (calendar == null) { - return null; - } - return MiscUtil.asDate(calendar); - } - - @Override - public void setObject(Date object) { - if (object == null) { - model.setObject(null); - } else { - model.setObject(MiscUtil.asXMLGregorianCalendar(object)); - } - } - }; - } - - private void initBodyLayout(WebMarkupContainer body) { - TextArea description = new TextArea<>(ID_DESCRIPTION, - new PropertyModel(getModel(), AssignmentEditorDto.F_DESCRIPTION)); - description.setEnabled(getModel().getObject().isEditable()); - body.add(description); - - WebMarkupContainer relationContainer = new WebMarkupContainer(ID_RELATION_CONTAINER); - relationContainer.setOutputMarkupId(true); - relationContainer.setOutputMarkupPlaceholderTag(true); - relationContainer.add(new VisibleEnableBehaviour(){ - - @Override - public boolean isVisible() { - AssignmentEditorDto dto = getModel().getObject(); - if(dto != null){ - if(AssignmentEditorDtoType.ORG_UNIT.equals(dto.getType())){ - return true; - } - } - - return false; - } - }); - body.add(relationContainer); - - TwoStateBooleanPanel relation = new TwoStateBooleanPanel(ID_RELATION, new PropertyModel(getModel(), AssignmentEditorDto.F_IS_ORG_UNIT_MANAGER), - "user.orgMember", "user.orgManager", null); - relation.setOutputMarkupId(true); - relation.setOutputMarkupPlaceholderTag(true); - relation.setPanelEnabled(getModel().getObject().isEditable()); - relation.add(new VisibleEnableBehaviour(){ - - @Override - public boolean isVisible() { - return isCreatingNewAssignment(); - } - }); - relationContainer.add(relation); - - Label relationLabel = new Label(ID_RELATION_LABEL, new AbstractReadOnlyModel() { - - @Override - public String getObject() { - if(getModel() == null || getModel().getObject() == null){ - return getString("AssignmentEditorPanel.relation.notSpecified"); - } - - AssignmentEditorDto object = getModel().getObject(); - return object.isOrgUnitManager() ? getString("user.orgManager") : getString("user.orgMember"); - } - }); - relationLabel.setOutputMarkupId(true); - relationLabel.setOutputMarkupPlaceholderTag(true); - relationLabel.add(new VisibleEnableBehaviour(){ - - @Override - public boolean isVisible() { - return !isCreatingNewAssignment(); - } - }); - relationContainer.add(relationLabel); - - WebMarkupContainer tenantRefContainer = createTenantContainer(); - body.add(tenantRefContainer); - - WebMarkupContainer orgRefContainer = createOrgContainer(); - body.add(orgRefContainer); - - WebMarkupContainer activationBlock = new WebMarkupContainer(ID_ACTIVATION_BLOCK); - activationBlock.add(new VisibleEnableBehaviour() { - - @Override - public boolean isVisible() { - //enabled activation in assignments for now. - return true; - } - }); - body.add(activationBlock); - - DropDownChoicePanel administrativeStatus = WebComponentUtil.createEnumPanel(ActivationStatusType.class, ID_ADMINISTRATIVE_STATUS, - new PropertyModel(getModel(), AssignmentEditorDto.F_ACTIVATION + "." - + ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart()), this); - administrativeStatus.setEnabled(getModel().getObject().isEditable()); - activationBlock.add(administrativeStatus); - - DateInput validFrom = new DateInput(ID_VALID_FROM, createDateModel(new PropertyModel(getModel(), - AssignmentEditorDto.F_ACTIVATION + ".validFrom"))); - validFrom.setEnabled(getModel().getObject().isEditable()); - activationBlock.add(validFrom); - - DateInput validTo = new DateInput(ID_VALID_TO, createDateModel(new PropertyModel(getModel(), - AssignmentEditorDto.F_ACTIVATION + ".validTo"))); - validTo.setEnabled(getModel().getObject().isEditable()); - activationBlock.add(validTo); - WebMarkupContainer targetContainer = new WebMarkupContainer(ID_TARGET_CONTAINER); - targetContainer.add(new VisibleEnableBehaviour() { - - @Override - public boolean isVisible() { - AssignmentEditorDto dto = getModel().getObject(); - return !AssignmentEditorDtoType.CONSTRUCTION.equals(dto.getType()); - } - }); - body.add(targetContainer); - - Label target = new Label(ID_TARGET, createTargetModel()); - targetContainer.add(target); - - WebMarkupContainer constructionContainer = new WebMarkupContainer(ID_CONSTRUCTION_CONTAINER); - constructionContainer.add(new VisibleEnableBehaviour() { - - @Override - public boolean isVisible() { - AssignmentEditorDto dto = getModel().getObject(); - return AssignmentEditorDtoType.CONSTRUCTION.equals(dto.getType()); - } - }); - body.add(constructionContainer); - - AjaxLink showEmpty = new AjaxLink(ID_SHOW_EMPTY) { - - @Override - public void onClick(AjaxRequestTarget target) { - showEmptyPerformed(target); - } - }; - constructionContainer.add(showEmpty); - - Label showEmptyLabel = new Label(ID_SHOW_EMPTY_LABEL, createShowEmptyLabel()); - showEmptyLabel.setOutputMarkupId(true); - showEmpty.add(showEmptyLabel); - - initAttributesLayout(constructionContainer); - - addAjaxOnUpdateBehavior(body); - } - - private WebMarkupContainer createTenantContainer(){ - WebMarkupContainer tenantRefContainer = new WebMarkupContainer(ID_CONTAINER_TENANT_REF); - ChooseTypePanel tenantRef = new ChooseTypePanel(ID_TENANT_CHOOSER, - new PropertyModel(getModel(), AssignmentEditorDto.F_TENANT_REF)){ - - @Override - protected ObjectQuery getChooseQuery(){ - ObjectQuery query = new ObjectQuery(); - - ObjectFilter filter = EqualFilter.createEqual(OrgType.F_TENANT, OrgType.class, - getPageBase().getPrismContext(), null, true); - query.setFilter(filter); - - return query; - } - - @Override - protected boolean isSearchEnabled() { - return true; - } - - @Override - protected QName getSearchProperty() { - return OrgType.F_NAME; - } - }; - tenantRef.setPanelEnabled(getModel().getObject().isEditable()); - tenantRefContainer.add(tenantRef); - tenantRefContainer.add(new VisibleEnableBehaviour(){ - - @Override - public boolean isVisible() { - AssignmentEditorDto dto = getModel().getObject(); - if(dto != null){ - if(AssignmentEditorDtoType.ROLE.equals(dto.getType())){ - return true; - } - } - - return false; - } - }); - return tenantRefContainer; - } - - private WebMarkupContainer createOrgContainer(){ - WebMarkupContainer tenantRefContainer = new WebMarkupContainer(ID_CONTAINER_ORG_REF); - ChooseTypePanel tenantRef = new ChooseTypePanel(ID_ORG_CHOOSER, - new PropertyModel(getModel(), AssignmentEditorDto.F_ORG_REF)){ - - @Override - protected ObjectQuery getChooseQuery(){ - ObjectQuery query = new ObjectQuery(); - - ObjectFilter filter = OrFilter.createOr( - EqualFilter.createEqual(OrgType.F_TENANT, OrgType.class, getPageBase().getPrismContext(), null, false), - EqualFilter.createEqual(OrgType.F_TENANT, OrgType.class, getPageBase().getPrismContext(), null, null)); - query.setFilter(filter); - - return query; - } - - @Override - protected boolean isSearchEnabled() { - return true; - } - - @Override - protected QName getSearchProperty() { - return OrgType.F_NAME; - } - }; - tenantRefContainer.add(tenantRef); - tenantRef.setEnabled(getModel().getObject().isEditable()); - tenantRefContainer.add(new VisibleEnableBehaviour(){ - - @Override - public boolean isVisible() { - AssignmentEditorDto dto = getModel().getObject(); - if(dto != null){ - if(AssignmentEditorDtoType.ROLE.equals(dto.getType())){ - return true; - } - } - - return false; - } - }); - return tenantRefContainer; - } - - private void addAjaxOnBlurUpdateBehaviorToComponent(final Component component){ - component.setOutputMarkupId(true); - component.add(new AjaxFormComponentUpdatingBehavior("blur") { - - @Override - protected void onUpdate(AjaxRequestTarget target) {} - }); - } - - private void addAjaxOnUpdateBehavior(WebMarkupContainer container){ - container.visitChildren(new IVisitor() { - @Override - public void component(Component component, IVisit objectIVisit) { - if(component instanceof InputPanel){ - addAjaxOnBlurUpdateBehaviorToComponent(((InputPanel) component).getBaseFormComponent()); - } else if(component instanceof FormComponent){ - addAjaxOnBlurUpdateBehaviorToComponent(component); - } - } - }); - } - - private void initAttributesLayout(WebMarkupContainer constructionContainer) { - WebMarkupContainer attributes = new WebMarkupContainer(ID_ATTRIBUTES); - attributes.setOutputMarkupId(true); - attributes.add(new VisibleEnableBehaviour() { - - @Override - public boolean isVisible() { - AssignmentEditorDto dto = getModel().getObject(); - return AssignmentEditorDtoType.CONSTRUCTION.equals(dto.getType()); - } - }); - attributes.setEnabled(getModel().getObject().isEditable()); - constructionContainer.add(attributes); - - ListView attribute = new ListView(ID_ATTRIBUTE, attributesModel){ - - @Override - protected void populateItem(ListItem listItem) { - final IModel attrModel = listItem.getModel(); - ACAttributePanel acAttribute = new ACAttributePanel(ID_AC_ATTRIBUTE, attrModel); - acAttribute.setRenderBodyOnly(true); - listItem.add(acAttribute); - listItem.setOutputMarkupId(true); - - listItem.add(new VisibleEnableBehaviour() { - - @Override - public boolean isVisible() { - AssignmentEditorDto editorDto = AssignmentEditorPanel.this.getModel().getObject(); - if (editorDto.isShowEmpty()) { - return true; - } - - ACAttributeDto dto = attrModel.getObject(); - return !dto.isEmpty(); - } - }); - } - }; - attributes.add(attribute); - //todo extension - } - - private IModel createShowEmptyLabel() { - return new AbstractReadOnlyModel() { - - @Override - public String getObject() { - AssignmentEditorDto dto = AssignmentEditorPanel.this.getModel().getObject(); - - if (dto.isShowEmpty()) { - return getString("AssignmentEditorPanel.hideEmpty"); - } else { - return getString("AssignmentEditorPanel.showEmpty"); - } - } - }; - } - - private void showEmptyPerformed(AjaxRequestTarget target) { - AssignmentEditorDto dto = AssignmentEditorPanel.this.getModel().getObject(); - dto.setShowEmpty(!dto.isShowEmpty()); - - WebMarkupContainer parent = (WebMarkupContainer) get(createComponentPath(ID_BODY, - ID_CONSTRUCTION_CONTAINER)); - - target.add(parent.get(ID_ATTRIBUTES), parent.get(createComponentPath(ID_SHOW_EMPTY, ID_SHOW_EMPTY_LABEL)), - getPageBase().getFeedbackPanel()); - } - - private List loadAttributes() { - AssignmentEditorDto dto = getModel().getObject(); - - if(dto.getAttributes() != null && !dto.getAttributes().isEmpty()){ - return dto.getAttributes(); - } - - OperationResult result = new OperationResult(OPERATION_LOAD_ATTRIBUTES); - List attributes = new ArrayList<>(); - try { - ConstructionType construction = WebComponentUtil.getContainerValue(dto.getOldValue(), - AssignmentType.F_CONSTRUCTION, ConstructionType.class); - - if(construction == null){ - return attributes; - } - - PrismObject resource = construction.getResource() != null - ? construction.getResource().asPrismObject() : null; - if (resource == null) { - resource = getReference(construction.getResourceRef(), result); - } - - PrismContext prismContext = getPageBase().getPrismContext(); - RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource, - LayerType.PRESENTATION, prismContext); - RefinedObjectClassDefinition objectClassDefinition = refinedSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, construction.getIntent()); - - if(objectClassDefinition == null){ - return attributes; - } - - PrismContainerDefinition definition = objectClassDefinition.toResourceAttributeContainerDefinition(); - - if (LOGGER.isTraceEnabled()) { + public String getObject() { + AssignmentEditorDto dto = getModel().getObject(); + ActivationType activation = dto.getActivation(); + if (activation == null) { + return "-"; + } + + ActivationStatusType status = activation.getAdministrativeStatus(); + String strEnabled = createStringResource(status, "lower", "ActivationStatusType.null") + .getString(); + + if (activation.getValidFrom() != null && activation.getValidTo() != null) { + return getString("AssignmentEditorPanel.enabledFromTo", strEnabled, + MiscUtil.asDate(activation.getValidFrom()), + MiscUtil.asDate(activation.getValidTo())); + } else if (activation.getValidFrom() != null) { + return getString("AssignmentEditorPanel.enabledFrom", strEnabled, + MiscUtil.asDate(activation.getValidFrom())); + } else if (activation.getValidTo() != null) { + return getString("AssignmentEditorPanel.enabledTo", strEnabled, + MiscUtil.asDate(activation.getValidTo())); + } + + return "-"; + } + }; + } + + private IModel createDateModel(final IModel model) { + return new Model() { + + @Override + public Date getObject() { + XMLGregorianCalendar calendar = model.getObject(); + if (calendar == null) { + return null; + } + return MiscUtil.asDate(calendar); + } + + @Override + public void setObject(Date object) { + if (object == null) { + model.setObject(null); + } else { + model.setObject(MiscUtil.asXMLGregorianCalendar(object)); + } + } + }; + } + + private void initBodyLayout(WebMarkupContainer body) { + TextArea description = new TextArea<>(ID_DESCRIPTION, + new PropertyModel(getModel(), AssignmentEditorDto.F_DESCRIPTION)); + description.setEnabled(getModel().getObject().isEditable()); + body.add(description); + + WebMarkupContainer relationContainer = new WebMarkupContainer(ID_RELATION_CONTAINER); + relationContainer.setOutputMarkupId(true); + relationContainer.setOutputMarkupPlaceholderTag(true); + relationContainer.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto dto = getModel().getObject(); + if (dto != null) { + if (AssignmentEditorDtoType.ORG_UNIT.equals(dto.getType())) { + return true; + } + } + + return false; + } + }); + body.add(relationContainer); + + TwoStateBooleanPanel relation = new TwoStateBooleanPanel(ID_RELATION, + new PropertyModel(getModel(), AssignmentEditorDto.F_IS_ORG_UNIT_MANAGER), + "user.orgMember", "user.orgManager", null) { + @Override + protected void onStateChanged(AjaxRequestTarget target, Boolean newValue) { + AssignmentEditorPanel.this.updateAssignmentName(target, newValue); + } + }; + relation.setOutputMarkupId(true); + relation.setOutputMarkupPlaceholderTag(true); + relation.setPanelEnabled(getModel().getObject().isEditable()); + relation.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + return isCreatingNewAssignment(); + } + }); + relationContainer.add(relation); + + Label relationLabel = new Label(ID_RELATION_LABEL, new AbstractReadOnlyModel() { + + @Override + public String getObject() { + if (getModel() == null || getModel().getObject() == null) { + return getString("AssignmentEditorPanel.relation.notSpecified"); + } + + AssignmentEditorDto object = getModel().getObject(); + return object.isOrgUnitManager() ? getString("user.orgManager") : getString("user.orgMember"); + } + }); + relationLabel.setOutputMarkupId(true); + relationLabel.setOutputMarkupPlaceholderTag(true); + relationLabel.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + return !isCreatingNewAssignment(); + } + }); + relationContainer.add(relationLabel); + + WebMarkupContainer tenantRefContainer = createTenantContainer(); + body.add(tenantRefContainer); + + WebMarkupContainer orgRefContainer = createOrgContainer(); + body.add(orgRefContainer); + + WebMarkupContainer activationBlock = new WebMarkupContainer(ID_ACTIVATION_BLOCK); + activationBlock.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + // enabled activation in assignments for now. + return true; + } + }); + body.add(activationBlock); + + DropDownChoicePanel administrativeStatus = WebComponentUtil.createEnumPanel( + ActivationStatusType.class, ID_ADMINISTRATIVE_STATUS, + new PropertyModel(getModel(), AssignmentEditorDto.F_ACTIVATION + "." + + ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart()), + this); + administrativeStatus.setEnabled(getModel().getObject().isEditable()); + activationBlock.add(administrativeStatus); + + DateInput validFrom = new DateInput(ID_VALID_FROM, + createDateModel(new PropertyModel(getModel(), + AssignmentEditorDto.F_ACTIVATION + ".validFrom"))); + validFrom.setEnabled(getModel().getObject().isEditable()); + activationBlock.add(validFrom); + + DateInput validTo = new DateInput(ID_VALID_TO, + createDateModel(new PropertyModel(getModel(), + AssignmentEditorDto.F_ACTIVATION + ".validTo"))); + validTo.setEnabled(getModel().getObject().isEditable()); + activationBlock.add(validTo); + WebMarkupContainer targetContainer = new WebMarkupContainer(ID_TARGET_CONTAINER); + targetContainer.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto dto = getModel().getObject(); + return !AssignmentEditorDtoType.CONSTRUCTION.equals(dto.getType()); + } + }); + body.add(targetContainer); + + Label target = new Label(ID_TARGET, createTargetModel()); + targetContainer.add(target); + + WebMarkupContainer constructionContainer = new WebMarkupContainer(ID_CONSTRUCTION_CONTAINER); + constructionContainer.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto dto = getModel().getObject(); + return AssignmentEditorDtoType.CONSTRUCTION.equals(dto.getType()); + } + }); + body.add(constructionContainer); + + AjaxLink showEmpty = new AjaxLink(ID_SHOW_EMPTY) { + + @Override + public void onClick(AjaxRequestTarget target) { + showEmptyPerformed(target); + } + }; + constructionContainer.add(showEmpty); + + Label showEmptyLabel = new Label(ID_SHOW_EMPTY_LABEL, createShowEmptyLabel()); + showEmptyLabel.setOutputMarkupId(true); + showEmpty.add(showEmptyLabel); + + initAttributesLayout(constructionContainer); + + addAjaxOnUpdateBehavior(body); + } + + private void updateAssignmentName(AjaxRequestTarget target, Boolean isManager){ + + Label nameLabel = new Label(ID_NAME_LABEL, createAssignmentNameLabelModel(isManager)); + nameLabel.setOutputMarkupId(true); + AjaxLink name = (AjaxLink) get(createComponentPath(ID_HEADER_ROW, ID_NAME)); + name.addOrReplace(nameLabel); + target.add(name); + } + + private WebMarkupContainer createTenantContainer() { + WebMarkupContainer tenantRefContainer = new WebMarkupContainer(ID_CONTAINER_TENANT_REF); + ChooseTypePanel tenantRef = new ChooseTypePanel(ID_TENANT_CHOOSER, + new PropertyModel(getModel(), AssignmentEditorDto.F_TENANT_REF)) { + + @Override + protected ObjectQuery getChooseQuery() { + ObjectQuery query = new ObjectQuery(); + + ObjectFilter filter = EqualFilter.createEqual(OrgType.F_TENANT, OrgType.class, + getPageBase().getPrismContext(), null, true); + query.setFilter(filter); + + return query; + } + + @Override + protected boolean isSearchEnabled() { + return true; + } + + @Override + protected QName getSearchProperty() { + return OrgType.F_NAME; + } + }; + tenantRef.setPanelEnabled(getModel().getObject().isEditable()); + tenantRefContainer.add(tenantRef); + tenantRefContainer.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto dto = getModel().getObject(); + if (dto != null) { + if (AssignmentEditorDtoType.ROLE.equals(dto.getType())) { + return true; + } + } + + return false; + } + }); + return tenantRefContainer; + } + + private WebMarkupContainer createOrgContainer() { + WebMarkupContainer tenantRefContainer = new WebMarkupContainer(ID_CONTAINER_ORG_REF); + ChooseTypePanel tenantRef = new ChooseTypePanel(ID_ORG_CHOOSER, + new PropertyModel(getModel(), AssignmentEditorDto.F_ORG_REF)) { + + @Override + protected ObjectQuery getChooseQuery() { + ObjectQuery query = new ObjectQuery(); + + ObjectFilter filter = OrFilter.createOr( + EqualFilter.createEqual(OrgType.F_TENANT, OrgType.class, + getPageBase().getPrismContext(), null, false), + EqualFilter.createEqual(OrgType.F_TENANT, OrgType.class, + getPageBase().getPrismContext(), null, null)); + query.setFilter(filter); + + return query; + } + + @Override + protected boolean isSearchEnabled() { + return true; + } + + @Override + protected QName getSearchProperty() { + return OrgType.F_NAME; + } + }; + tenantRefContainer.add(tenantRef); + tenantRef.setEnabled(getModel().getObject().isEditable()); + tenantRefContainer.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto dto = getModel().getObject(); + if (dto != null) { + if (AssignmentEditorDtoType.ROLE.equals(dto.getType())) { + return true; + } + } + + return false; + } + }); + return tenantRefContainer; + } + + private void addAjaxOnBlurUpdateBehaviorToComponent(final Component component) { + component.setOutputMarkupId(true); + component.add(new AjaxFormComponentUpdatingBehavior("blur") { + + @Override + protected void onUpdate(AjaxRequestTarget target) { + } + }); + } + + private void addAjaxOnUpdateBehavior(WebMarkupContainer container) { + container.visitChildren(new IVisitor() { + @Override + public void component(Component component, IVisit objectIVisit) { + if (component instanceof InputPanel) { + addAjaxOnBlurUpdateBehaviorToComponent(((InputPanel) component).getBaseFormComponent()); + } else if (component instanceof FormComponent) { + addAjaxOnBlurUpdateBehaviorToComponent(component); + } + } + }); + } + + private void initAttributesLayout(WebMarkupContainer constructionContainer) { + WebMarkupContainer attributes = new WebMarkupContainer(ID_ATTRIBUTES); + attributes.setOutputMarkupId(true); + attributes.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto dto = getModel().getObject(); + return AssignmentEditorDtoType.CONSTRUCTION.equals(dto.getType()); + } + }); + attributes.setEnabled(getModel().getObject().isEditable()); + constructionContainer.add(attributes); + + ListView attribute = new ListView(ID_ATTRIBUTE, attributesModel) { + + @Override + protected void populateItem(ListItem listItem) { + final IModel attrModel = listItem.getModel(); + ACAttributePanel acAttribute = new ACAttributePanel(ID_AC_ATTRIBUTE, attrModel); + acAttribute.setRenderBodyOnly(true); + listItem.add(acAttribute); + listItem.setOutputMarkupId(true); + + listItem.add(new VisibleEnableBehaviour() { + + @Override + public boolean isVisible() { + AssignmentEditorDto editorDto = AssignmentEditorPanel.this.getModel().getObject(); + if (editorDto.isShowEmpty()) { + return true; + } + + ACAttributeDto dto = attrModel.getObject(); + return !dto.isEmpty(); + } + }); + } + }; + attributes.add(attribute); + // todo extension + } + + private IModel createShowEmptyLabel() { + return new AbstractReadOnlyModel() { + + @Override + public String getObject() { + AssignmentEditorDto dto = AssignmentEditorPanel.this.getModel().getObject(); + + if (dto.isShowEmpty()) { + return getString("AssignmentEditorPanel.hideEmpty"); + } else { + return getString("AssignmentEditorPanel.showEmpty"); + } + } + }; + } + + private void showEmptyPerformed(AjaxRequestTarget target) { + AssignmentEditorDto dto = AssignmentEditorPanel.this.getModel().getObject(); + dto.setShowEmpty(!dto.isShowEmpty()); + + WebMarkupContainer parent = (WebMarkupContainer) get( + createComponentPath(ID_BODY, ID_CONSTRUCTION_CONTAINER)); + + target.add(parent.get(ID_ATTRIBUTES), + parent.get(createComponentPath(ID_SHOW_EMPTY, ID_SHOW_EMPTY_LABEL)), + getPageBase().getFeedbackPanel()); + } + + private List loadAttributes() { + AssignmentEditorDto dto = getModel().getObject(); + + if (dto.getAttributes() != null && !dto.getAttributes().isEmpty()) { + return dto.getAttributes(); + } + + OperationResult result = new OperationResult(OPERATION_LOAD_ATTRIBUTES); + List attributes = new ArrayList<>(); + try { + ConstructionType construction = WebComponentUtil.getContainerValue(dto.getOldValue(), + AssignmentType.F_CONSTRUCTION, ConstructionType.class); + + if (construction == null) { + return attributes; + } + + PrismObject resource = construction.getResource() != null + ? construction.getResource().asPrismObject() : null; + if (resource == null) { + resource = getReference(construction.getResourceRef(), result); + } + + PrismContext prismContext = getPageBase().getPrismContext(); + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource, + LayerType.PRESENTATION, prismContext); + RefinedObjectClassDefinition objectClassDefinition = refinedSchema + .getRefinedDefinition(ShadowKindType.ACCOUNT, construction.getIntent()); + + if (objectClassDefinition == null) { + return attributes; + } + + PrismContainerDefinition definition = objectClassDefinition + .toResourceAttributeContainerDefinition(); + + if (LOGGER.isTraceEnabled()) { LOGGER.trace("Refined definition for {}\n{}", construction, definition.debugDump()); } - List attrConstructions = construction.getAttribute(); - - Collection definitions = definition.getDefinitions(); - for (ItemDefinition attrDef : definitions) { - if (!(attrDef instanceof PrismPropertyDefinition)) { - //log skipping or something... - continue; - } - - PrismPropertyDefinition propertyDef = (PrismPropertyDefinition) attrDef; - if (propertyDef.isOperational() || propertyDef.isIgnored()) { - continue; - } - attributes.add(ACAttributeDto.createACAttributeDto(propertyDef, - findOrCreateValueConstruction(propertyDef, attrConstructions), prismContext)); - } - result.recordSuccess(); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "Exception occurred during assignment attribute loading", ex); - result.recordFatalError("Exception occurred during assignment attribute loading.", ex); - } finally { - result.recomputeStatus(); - } - - Collections.sort(attributes, new Comparator() { - - @Override - public int compare(ACAttributeDto a1, ACAttributeDto a2) { - return String.CASE_INSENSITIVE_ORDER.compare(a1.getName(), a2.getName()); - } - }); - - dto.setAttributes(attributes); - - getPageBase().showResult(result, false); - - return dto.getAttributes(); - } - - private PrismObject getReference(ObjectReferenceType ref, OperationResult result) { - OperationResult subResult = result.createSubresult(OPERATION_LOAD_RESOURCE); - subResult.addParam("targetRef", ref.getOid()); - PrismObject target = null; - try { - Task task = getPageBase().createSimpleTask(OPERATION_LOAD_RESOURCE); - Class type = ObjectType.class; - if (ref.getType() != null){ - type = getPageBase().getPrismContext().getSchemaRegistry().determineCompileTimeClass(ref.getType()); - } - target = getPageBase().getModelService().getObject(type, ref.getOid(), null, task, - subResult); - subResult.recordSuccess(); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "Couldn't get account construction resource ref", ex); - subResult.recordFatalError("Couldn't get account construction resource ref.", ex); - } - - return target; - } - - private ResourceAttributeDefinitionType findOrCreateValueConstruction(PrismPropertyDefinition attrDef, - List attrConstructions) { - for (ResourceAttributeDefinitionType construction : attrConstructions) { - if (attrDef.getName().equals(construction.getRef())) { - return construction; - } - } - - ResourceAttributeDefinitionType construction = new ResourceAttributeDefinitionType(); - construction.setRef(new ItemPathType(new ItemPath(attrDef.getName()))); - - return construction; - } - - private IModel createImageTypeModel(final IModel model) { - return new AbstractReadOnlyModel() { + List attrConstructions = construction.getAttribute(); + + Collection definitions = definition.getDefinitions(); + for (ItemDefinition attrDef : definitions) { + if (!(attrDef instanceof PrismPropertyDefinition)) { + // log skipping or something... + continue; + } + + PrismPropertyDefinition propertyDef = (PrismPropertyDefinition) attrDef; + if (propertyDef.isOperational() || propertyDef.isIgnored()) { + continue; + } + attributes.add(ACAttributeDto.createACAttributeDto(propertyDef, + findOrCreateValueConstruction(propertyDef, attrConstructions), prismContext)); + } + result.recordSuccess(); + } catch (Exception ex) { + LoggingUtils.logException(LOGGER, "Exception occurred during assignment attribute loading", ex); + result.recordFatalError("Exception occurred during assignment attribute loading.", ex); + } finally { + result.recomputeStatus(); + } + + Collections.sort(attributes, new Comparator() { + + @Override + public int compare(ACAttributeDto a1, ACAttributeDto a2) { + return String.CASE_INSENSITIVE_ORDER.compare(a1.getName(), a2.getName()); + } + }); + + dto.setAttributes(attributes); + + getPageBase().showResult(result, false); + + return dto.getAttributes(); + } + + private PrismObject getReference(ObjectReferenceType ref, OperationResult result) { + OperationResult subResult = result.createSubresult(OPERATION_LOAD_RESOURCE); + subResult.addParam("targetRef", ref.getOid()); + PrismObject target = null; + try { + Task task = getPageBase().createSimpleTask(OPERATION_LOAD_RESOURCE); + Class type = ObjectType.class; + if (ref.getType() != null) { + type = getPageBase().getPrismContext().getSchemaRegistry() + .determineCompileTimeClass(ref.getType()); + } + target = getPageBase().getModelService().getObject(type, ref.getOid(), null, task, subResult); + subResult.recordSuccess(); + } catch (Exception ex) { + LoggingUtils.logException(LOGGER, "Couldn't get account construction resource ref", ex); + subResult.recordFatalError("Couldn't get account construction resource ref.", ex); + } + + return target; + } + + private ResourceAttributeDefinitionType findOrCreateValueConstruction(PrismPropertyDefinition attrDef, + List attrConstructions) { + for (ResourceAttributeDefinitionType construction : attrConstructions) { + if (attrDef.getName().equals(construction.getRef())) { + return construction; + } + } + + ResourceAttributeDefinitionType construction = new ResourceAttributeDefinitionType(); + construction.setRef(new ItemPathType(new ItemPath(attrDef.getName()))); + + return construction; + } + + private IModel createImageTypeModel(final IModel model) { + return new AbstractReadOnlyModel() { private static final long serialVersionUID = 1L; @Override - public String getObject() { - AssignmentEditorDto assignmentEditorDto = model.getObject(); - - PrismObject targetObject = null; - try { - targetObject = getTargetObject(assignmentEditorDto); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "Couldn't load object", ex); - // Otherwise ignore, will be pocessed by the fallback code below - } - - if (targetObject == null) { - AssignmentEditorDtoType type = assignmentEditorDto.getType(); - return type.getIconCssClass(); - } else { - return WebComponentUtil.createDefaultIcon(targetObject); - } - } - }; - } - - private void nameClickPerformed(AjaxRequestTarget target) { - AssignmentEditorDto dto = getModel().getObject(); - boolean minimized = dto.isMinimized(); - dto.setMinimized(!minimized); - - target.add(this); - } - - private IModel createTargetModel() { - return new LoadableModel(false) { + public String getObject() { + AssignmentEditorDto assignmentEditorDto = model.getObject(); + + PrismObject targetObject = null; + try { + targetObject = getTargetObject(assignmentEditorDto); + } catch (Exception ex) { + LoggingUtils.logException(LOGGER, "Couldn't load object", ex); + // Otherwise ignore, will be pocessed by the fallback code + // below + } + + if (targetObject == null) { + AssignmentEditorDtoType type = assignmentEditorDto.getType(); + return type.getIconCssClass(); + } else { + return WebComponentUtil.createDefaultIcon(targetObject); + } + } + }; + } + + private void nameClickPerformed(AjaxRequestTarget target) { + AssignmentEditorDto dto = getModel().getObject(); + boolean minimized = dto.isMinimized(); + dto.setMinimized(!minimized); + + target.add(this); + } + + private IModel createTargetModel() { + return new LoadableModel(false) { private static final long serialVersionUID = 1L; @Override - protected String load() { - AssignmentEditorDto dto = getModel().getObject(); - - PrismObject targetObject; - try { - targetObject = getTargetObject(dto); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "Couldn't load object", ex); - return getString("AssignmentEditorPanel.loadError"); - } - - if (targetObject == null) { - return getString("AssignmentEditorPanel.undefined"); - } - - return WebComponentUtil.getName(targetObject); - } - }; - } - - private PrismObject getTargetObject(AssignmentEditorDto dto) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException { - PrismContainerValue assignment = dto.getOldValue(); - - PrismReference targetRef = assignment.findReference(AssignmentType.F_TARGET_REF); - if (targetRef == null) { - return null; - } - - PrismReferenceValue refValue = targetRef.getValue(); - if (refValue != null && refValue.getObject() != null) { - PrismObject object = refValue.getObject(); - return object; - } - - String oid = targetRef.getOid(); - OperationResult result = new OperationResult(OPERATION_LOAD_OBJECT); - - PageBase page = getPageBase(); - ModelService model = page.getMidpointApplication().getModel(); - Task task = page.createSimpleTask(OPERATION_LOAD_OBJECT); - - Collection> options = - SelectorOptions.createCollection(GetOperationOptions.createNoFetch()); - Class type = (Class) ObjectType.class; - if (refValue.getTargetType() != null){ - type = getPageBase().getPrismContext().getSchemaRegistry().determineCompileTimeClass(refValue.getTargetType()); - } - PrismObject object = model.getObject(type, oid, options, task, result); - refValue.setObject(object); - return object; - } - - private void showErrorPerformed(AjaxRequestTarget target){ - error(getString("AssignmentEditorPanel.targetError")); - target.add(getPageBase().getFeedbackPanel()); - } - - /** - * Override to provide the information if object that contains this assignment - * is being edited or created. - * */ - protected boolean isCreatingNewAssignment(){ - if(getModelObject() == null){ - return false; - } - - return UserDtoStatus.ADD.equals(getModelObject().getStatus()); - } + protected String load() { + AssignmentEditorDto dto = getModel().getObject(); + + PrismObject targetObject; + try { + targetObject = getTargetObject(dto); + } catch (Exception ex) { + LoggingUtils.logException(LOGGER, "Couldn't load object", ex); + return getString("AssignmentEditorPanel.loadError"); + } + + if (targetObject == null) { + return getString("AssignmentEditorPanel.undefined"); + } + + return WebComponentUtil.getName(targetObject); + } + }; + } + + private PrismObject getTargetObject(AssignmentEditorDto dto) + throws ObjectNotFoundException, SchemaException, SecurityViolationException, + CommunicationException, ConfigurationException { + PrismContainerValue assignment = dto.getOldValue(); + + PrismReference targetRef = assignment.findReference(AssignmentType.F_TARGET_REF); + if (targetRef == null) { + return null; + } + + PrismReferenceValue refValue = targetRef.getValue(); + if (refValue != null && refValue.getObject() != null) { + PrismObject object = refValue.getObject(); + return object; + } + + String oid = targetRef.getOid(); + OperationResult result = new OperationResult(OPERATION_LOAD_OBJECT); + + PageBase page = getPageBase(); + ModelService model = page.getMidpointApplication().getModel(); + Task task = page.createSimpleTask(OPERATION_LOAD_OBJECT); + + Collection> options = SelectorOptions + .createCollection(GetOperationOptions.createNoFetch()); + Class type = (Class) ObjectType.class; + if (refValue.getTargetType() != null) { + type = getPageBase().getPrismContext().getSchemaRegistry() + .determineCompileTimeClass(refValue.getTargetType()); + } + PrismObject object = model.getObject(type, oid, options, task, result); + refValue.setObject(object); + return object; + } + + private void showErrorPerformed(AjaxRequestTarget target) { + error(getString("AssignmentEditorPanel.targetError")); + target.add(getPageBase().getFeedbackPanel()); + } + + /** + * Override to provide the information if object that contains this + * assignment is being edited or created. + */ + protected boolean isCreatingNewAssignment() { + if (getModelObject() == null) { + return false; + } + + return UserDtoStatus.ADD.equals(getModelObject().getStatus()); + } } From b8e843dedbc44d9892bf0ff99bf3b2855f68e2a8 Mon Sep 17 00:00:00 2001 From: Katarina Valalikova Date: Tue, 3 May 2016 13:23:16 +0200 Subject: [PATCH 04/12] small cleanup, remove unused lines of code. --- .../web/page/admin/resources/ResourceContentTabPanel.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ResourceContentTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ResourceContentTabPanel.java index 1bde924ff9b..3e50b74ae18 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ResourceContentTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ResourceContentTabPanel.java @@ -210,7 +210,6 @@ public boolean isVisible() { @Override public void onClick(AjaxRequestTarget target) { resourceSearchModel.setObject(Boolean.FALSE); -// mainForm.addOrReplace(initResourceContent(model)); mainForm.addOrReplace(initRepoContent(model)); target.add(getParent().addOrReplace(mainForm)); target.add(this); @@ -232,7 +231,6 @@ protected void onBeforeRender() { public void onClick(AjaxRequestTarget target) { resourceSearchModel.setObject(Boolean.TRUE); mainForm.addOrReplace(initResourceContent(model)); -// mainForm.addOrReplace(initRepoContent(model)); target.add(getParent().addOrReplace(mainForm)); target.add(this.add(AttributeModifier.append("class", " active"))); target.add(getParent().get(ID_REPO_SEARCH).add(AttributeModifier.replace("class", "btn btn-sm btn-default"))); From af694214af85492eb331508945f52e5fb119bb35 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 3 May 2016 19:18:37 +0200 Subject: [PATCH 05/12] Cleanup of query serialization (MID-2771) - first step. Added GT/GE/LT/LE filters. --- build-system/pom.xml | 11 + .../prism/PrismContainerDefinition.java | 10 +- .../midpoint/prism/parser/QueryConvertor.java | 736 +++++++++--------- .../midpoint/prism/parser/XPathHolder.java | 47 +- .../prism/path/IdentifierPathSegment.java | 11 +- .../midpoint/prism/path/ItemPath.java | 38 +- .../path/ObjectReferencePathSegment.java | 11 +- .../prism/path/ParentPathSegment.java | 11 +- .../midpoint/prism/query/AllFilter.java | 9 + .../midpoint/prism/query/AndFilter.java | 4 + .../prism/query/ComparativeFilter.java | 32 +- .../midpoint/prism/query/EqualFilter.java | 17 +- .../midpoint/prism/query/ExistsFilter.java | 49 +- .../midpoint/prism/query/GreaterFilter.java | 38 +- .../midpoint/prism/query/InFilter.java | 5 + .../midpoint/prism/query/InOidFilter.java | 50 +- .../midpoint/prism/query/LessFilter.java | 50 +- .../midpoint/prism/query/LogicalFilter.java | 18 +- .../midpoint/prism/query/NoneFilter.java | 11 + .../midpoint/prism/query/NotFilter.java | 6 + .../midpoint/prism/query/ObjectFilter.java | 2 + .../midpoint/prism/query/ObjectOrdering.java | 26 + .../midpoint/prism/query/ObjectPaging.java | 44 ++ .../midpoint/prism/query/ObjectQuery.java | 35 + .../midpoint/prism/query/OrFilter.java | 6 + .../midpoint/prism/query/OrgFilter.java | 4 +- .../prism/query/PropertyValueFilter.java | 133 ++-- .../prism/query/QueryJaxbConvertor.java | 18 +- .../midpoint/prism/query/RefFilter.java | 6 + .../midpoint/prism/query/SubstringFilter.java | 35 +- .../midpoint/prism/query/TypeFilter.java | 3 +- .../midpoint/prism/query/UndefinedFilter.java | 11 + .../midpoint/prism/query/ValueFilter.java | 14 +- .../prism/query/builder/R_AtomicFilter.java | 33 +- .../prism/query/builder/S_ConditionEntry.java | 11 +- .../midpoint/prism/schema/SchemaRegistry.java | 43 +- .../midpoint/prism/util/PrismTestUtil.java | 10 + .../_public/types_3/ObjectReferenceType.java | 36 +- .../main/resources/xml/ns/public/query-3.xsd | 268 ++++--- .../main/resources/xml/ns/public/types-3.xsd | 12 + .../evolveum/midpoint/prism/TestDelta.java | 1 - infra/schema/pom.xml | 15 + .../midpoint/schema/TestQueryConvertor.java | 393 +++++++--- .../midpoint/schema/test/XPathTest.java | 17 + .../queryconvertor/filter-account.xml | 4 +- .../resources/queryconvertor/test100All.xml | 22 + .../resources/queryconvertor/test110None.xml | 22 + .../queryconvertor/test120Undefined.xml | 22 + .../resources/queryconvertor/test200Equal.xml | 26 + .../queryconvertor/test210EqualMultiple.xml | 26 + .../test220EqualRightHandItem.xml | 25 + .../queryconvertor/test300Greater.xml | 25 + .../queryconvertor/test310AllComparisons.xml | 43 + .../queryconvertor/test350Substring.xml | 43 + .../resources/queryconvertor/test360Ref.xml | 44 ++ .../queryconvertor/test365RefTwoWay.xml | 38 + .../queryconvertor/test400OrgFilterRoot.xml | 24 + .../test410OrgFilterSubtree.xml | 11 + .../queryconvertor/test420OrgFilterDirect.xml | 27 + .../test430OrgFilterDefaultScope.xml | 27 + .../resources/queryconvertor/test500InOid.xml | 26 + .../queryconvertor/test510InOidContainer.xml | 32 + .../queryconvertor/test590Logicals.xml | 35 + .../resources/queryconvertor/test600Type.xml | 30 + .../queryconvertor/test700Exists.xml | 44 ++ .../impl/AccCertQueryHelper.java | 7 +- .../midpoint/repo/sql/CertificationTest.java | 7 +- .../repo/sql/QueryInterpreter2Test.java | 11 +- .../repo/sql/ObjectPagingAfterOid.java | 21 + .../restriction/AnyPropertyRestriction.java | 2 +- .../restriction/PropertyRestriction.java | 6 +- .../testing/model/client/sample/Main.java | 2 +- 72 files changed, 2097 insertions(+), 895 deletions(-) create mode 100644 infra/schema/src/test/resources/queryconvertor/test100All.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test110None.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test120Undefined.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test200Equal.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test210EqualMultiple.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test220EqualRightHandItem.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test300Greater.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test310AllComparisons.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test350Substring.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test360Ref.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test365RefTwoWay.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test400OrgFilterRoot.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test410OrgFilterSubtree.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test420OrgFilterDirect.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test430OrgFilterDefaultScope.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test500InOid.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test510InOidContainer.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test590Logicals.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test600Type.xml create mode 100644 infra/schema/src/test/resources/queryconvertor/test700Exists.xml diff --git a/build-system/pom.xml b/build-system/pom.xml index 1c18085db8d..78a61d93341 100644 --- a/build-system/pom.xml +++ b/build-system/pom.xml @@ -67,6 +67,7 @@ 4.0.4.RELEASE 6.8.8 1.2 + 2.1.1 2.2.3 4.3.8.Final 1.3.171 @@ -753,6 +754,16 @@ testng ${testng.version} + + org.xmlunit + xmlunit-core + ${xmlunit.version} + + + org.xmlunit + xmlunit-legacy + ${xmlunit.version} + xml-resolver xml-resolver 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 308a5c23560..42cae34c972 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 @@ -227,8 +227,14 @@ public ID findItemDefinition(ItemPath path, Class ObjectQuery parseQuery(MapXNode xmap, Class clazz, PrismContext prismContext) - throws SchemaException { + // please keep the order of filter clause symbols synchronized with query-3.xsd - if (xmap == null){ - return null; - } - - PrismObjectDefinition objDef = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(clazz); + private static final QName CLAUSE_ALL = new QName(NS_QUERY, "all"); + private static final QName CLAUSE_NONE = new QName(NS_QUERY, "none"); + private static final QName CLAUSE_UNDEFINED = new QName(NS_QUERY, "undefined"); - if (objDef == null) { - throw new SchemaException("Cannot find obj definition for "+clazz); - } + private static final QName CLAUSE_EQUAL = new QName(NS_QUERY, "equal"); + private static final QName CLAUSE_GREATER = new QName(NS_QUERY, "greater"); + private static final QName CLAUSE_GREATER_OR_EQUAL = new QName(NS_QUERY, "greaterOrEqual"); + private static final QName CLAUSE_LESS = new QName(NS_QUERY, "less"); + private static final QName CLAUSE_LESS_OR_EQUAL = new QName(NS_QUERY, "lessOrEqual"); + private static final QName CLAUSE_SUBSTRING = new QName(NS_QUERY, "substring"); - return parseQuery(xmap, objDef); - } - - public static ObjectQuery parseQuery(MapXNode xmap, PrismObjectDefinition objDef) throws SchemaException { - if (xmap == null){ - return null; - } - - XNode xnodeFilter = xmap.get(KEY_FILTER); - if (xnodeFilter != null) { - throw new SchemaException("No filter in query"); - } - if (!(xnodeFilter instanceof MapXNode)) { - throw new SchemaException("Cannot parse filter from "+xnodeFilter); - } - ObjectFilter filter = parseFilter((MapXNode)xnodeFilter, objDef); - - ObjectQuery query = new ObjectQuery(); - query.setFilter(filter); - - XNode xnodePaging = xmap.get(KEY_PAGING); - if (xnodePaging != null) { - throw new UnsupportedOperationException("work in progress"); -// ObjectPaging paging = PagingConvertor.parsePaging(xnodePaging); -// query.setPaging(paging); - } + private static final QName CLAUSE_REF = new QName(NS_QUERY, "ref"); + private static final QName CLAUSE_ORG = new QName(NS_QUERY, "org"); + private static final QName CLAUSE_IN_OID = new QName(NS_QUERY, "inOid"); + + private static final QName CLAUSE_AND = new QName(NS_QUERY, "and"); + private static final QName CLAUSE_OR = new QName(NS_QUERY, "or"); + private static final QName CLAUSE_NOT = new QName(NS_QUERY, "not"); + + private static final QName CLAUSE_TYPE = new QName(NS_QUERY, "type"); + private static final QName CLAUSE_EXISTS = new QName(NS_QUERY, "exists"); + + // common elements + private static final QName ELEMENT_PATH = new QName(NS_QUERY, "path"); + private static final QName ELEMENT_MATCHING = new QName(NS_QUERY, "matching"); + private static final QName ELEMENT_VALUE = new QName(NS_QUERY, "value"); + private static final QName ELEMENT_RIGHT_HAND_SIDE_PATH = new QName(NS_QUERY, "rightHandSidePath"); + + // substring + private static final QName ELEMENT_ANCHOR_START = new QName(NS_QUERY, "anchorStart"); + private static final QName ELEMENT_ANCHOR_END = new QName(NS_QUERY, "anchorEnd"); + + // org + private static final QName ELEMENT_ORG_REF = new QName(NS_QUERY, "orgRef"); + private static final QName ELEMENT_SCOPE = new QName(NS_QUERY, "scope"); + private static final QName ELEMENT_IS_ROOT = new QName(NS_QUERY, "isRoot"); + + // inOid + private static final QName ELEMENT_OID = new QName(NS_QUERY, "oid"); + private static final QName ELEMENT_CONSIDER_OWNER = new QName(NS_QUERY, "considerOwner"); + + // type and exists + public static final QName ELEMENT_TYPE = new QName(NS_QUERY, "type"); + private static final QName ELEMENT_FILTER = new QName(NS_QUERY, "filter"); - return query; - } - /** * Used by XNodeProcessor and similar code that does not have complete schema for the filter */ public static ObjectFilter parseFilter(XNode xnode, PrismContext prismContext) throws SchemaException { Validate.notNull(prismContext); MapXNode xmap = toMap(xnode); - return parseFilterContainer(xmap, null, false, prismContext); + return parseFilterInternal(xmap, null, false, prismContext); } - public static ObjectFilter parseFilter(MapXNode xmap, PrismObjectDefinition objDef) throws SchemaException { + public static ObjectFilter parseFilter(MapXNode xmap, PrismContainerDefinition objDef) throws SchemaException { Validate.notNull(objDef); if (xmap == null) { return null; } - return parseFilterContainer(xmap, objDef, false, objDef.getPrismContext()); + return parseFilterInternal(xmap, objDef, false, objDef.getPrismContext()); } public static ObjectFilter parseFilter(SearchFilterType filter, Class clazz, PrismContext prismContext) throws SchemaException { @@ -174,67 +138,75 @@ public static ObjectFilter parseFilter(SearchFilterType filter, PrismObjectDefin return parseFilter(filter.getFilterClauseXNode(), objDef); } - // beware, pcd may be null - private static ObjectFilter parseFilterContainer(MapXNode xmap, PrismContainerDefinition pcd, - boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { + private static ObjectFilter parseFilterInternal( + @NotNull MapXNode filterXMap, + @Nullable PrismContainerDefinition pcd, + boolean preliminaryParsingOnly, + @NotNull PrismContext prismContext) throws SchemaException { + Validate.notNull(prismContext); - Entry entry = xmap.getSingleEntryThatDoesNotMatch(SearchFilterType.F_DESCRIPTION); - QName filterQName = entry.getKey(); - XNode xsubnode = entry.getValue(); - return parseFilterContainer(xsubnode, filterQName, pcd, preliminaryParsingOnly, prismContext); + Entry clauseEntry = filterXMap.getSingleEntryThatDoesNotMatch(SearchFilterType.F_DESCRIPTION); + QName clauseQName = clauseEntry.getKey(); + XNode clauseContent = clauseEntry.getValue(); + return parseFilterInternal(clauseContent, clauseQName, pcd, preliminaryParsingOnly, prismContext); } - private static ObjectFilter parseFilterContainer(XNode xsubnode, QName filterQName, + private static ObjectFilter parseFilterInternal(XNode clauseContent, QName clauseQName, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { - - if (QNameUtil.match(filterQName, KEY_FILTER_AND)) { - return parseAndFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); - } - - if (QNameUtil.match(filterQName, KEY_FILTER_OR)) { - return parseOrFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); - } - - if (QNameUtil.match(filterQName, KEY_FILTER_NOT)) { - return parseNotFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); - } - - if (QNameUtil.match(filterQName, KEY_FILTER_EQUAL)) { - return parseEqualFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); - } - if (QNameUtil.match(filterQName, KEY_FILTER_REF)) { - return parseRefFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); + // trivial filters + if (QNameUtil.match(clauseQName, CLAUSE_ALL)) { + return new AllFilter(); + } else if (QNameUtil.match(clauseQName, CLAUSE_NONE)) { + return new NoneFilter(); + } else if (QNameUtil.match(clauseQName, CLAUSE_UNDEFINED)) { + return new UndefinedFilter(); } - if (QNameUtil.match(filterQName, KEY_FILTER_SUBSTRING)) { - return parseSubstringFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); - } + // primitive filters + MapXNode clauseXMap = toMap(clauseContent); - if (QNameUtil.match(filterQName, KEY_FILTER_ORG)) { - return parseOrgFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); - } - - if (QNameUtil.match(filterQName, KEY_FILTER_TYPE)) { - return parseTypeFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); + if (QNameUtil.match(clauseQName, CLAUSE_EQUAL) + || QNameUtil.match(clauseQName, CLAUSE_GREATER) + || QNameUtil.match(clauseQName, CLAUSE_GREATER_OR_EQUAL) + || QNameUtil.match(clauseQName, CLAUSE_LESS) + || QNameUtil.match(clauseQName, CLAUSE_LESS_OR_EQUAL)) { + return parseComparisonFilter(clauseQName, clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_SUBSTRING)) { + return parseSubstringFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_REF)) { + return parseRefFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_ORG)) { + return parseOrgFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_IN_OID)) { + return parseInOidFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); } - - if (QNameUtil.match(filterQName, KEY_FILTER_IN_OID)) { - return parseInOidFilter(xsubnode, pcd, preliminaryParsingOnly, prismContext); + + // logical filters + + if (QNameUtil.match(clauseQName, CLAUSE_AND)) { + return parseAndFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_OR)) { + return parseOrFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_NOT)) { + return parseNotFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); } - if (QNameUtil.match(filterQName, KEY_FILTER_NONE_TYPE)) { - return new NoneFilter(); + // other complex filters + + if (QNameUtil.match(clauseQName, CLAUSE_TYPE)) { + return parseTypeFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); + } else if (QNameUtil.match(clauseQName, CLAUSE_EXISTS)) { + return parseExistsFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); } - throw new UnsupportedOperationException("Unsupported query filter " + filterQName); + throw new UnsupportedOperationException("Unsupported query filter " + clauseQName); } - private static AndFilter parseAndFilter(XNode xnode, PrismContainerDefinition pcd, + private static AndFilter parseAndFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { - - List subfilters = parseLogicalFilter(xnode, pcd, preliminaryParsingOnly, prismContext); + List subfilters = parseLogicalFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); if (preliminaryParsingOnly) { return null; } else { @@ -242,21 +214,20 @@ private static AndFilter parseAndFilter(XNode xnode, P } } - private static List parseLogicalFilter(XNode xnode, + private static List parseLogicalFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { List subfilters = new ArrayList(); - MapXNode xmap = toMap(xnode); - for (Entry entry : xmap.entrySet()) { + for (Entry entry : clauseXMap.entrySet()) { if (entry.getValue() instanceof ListXNode){ Iterator subNodes = ((ListXNode) entry.getValue()).iterator(); while (subNodes.hasNext()){ - ObjectFilter subFilter = parseFilterContainer(subNodes.next(), entry.getKey(), pcd, preliminaryParsingOnly, prismContext); + ObjectFilter subFilter = parseFilterInternal(subNodes.next(), entry.getKey(), pcd, preliminaryParsingOnly, prismContext); if (!preliminaryParsingOnly) { subfilters.add(subFilter); } } } else{ - ObjectFilter subfilter = parseFilterContainer(entry.getValue(), entry.getKey(), pcd, preliminaryParsingOnly, prismContext); + ObjectFilter subfilter = parseFilterInternal(entry.getValue(), entry.getKey(), pcd, preliminaryParsingOnly, prismContext); if (!preliminaryParsingOnly) { subfilters.add(subfilter); } @@ -265,9 +236,9 @@ private static List parseLogicalFilter(X return subfilters; } - private static OrFilter parseOrFilter(XNode xnode, PrismContainerDefinition pcd, + private static OrFilter parseOrFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { - List subfilters = parseLogicalFilter(xnode, pcd, preliminaryParsingOnly, prismContext); + List subfilters = parseLogicalFilter(clauseXMap, pcd, preliminaryParsingOnly, prismContext); if (preliminaryParsingOnly) { return null; } else { @@ -275,11 +246,10 @@ private static OrFilter parseOrFilter(XNode xnode, Pri } } - private static NotFilter parseNotFilter(XNode xnode, PrismContainerDefinition pcd, + private static NotFilter parseNotFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { - MapXNode xmap = toMap(xnode); - Entry entry = singleSubEntry(xmap, "not"); - ObjectFilter subfilter = parseFilterContainer(entry.getValue(), entry.getKey(), pcd, preliminaryParsingOnly, prismContext); + Entry entry = singleSubEntry(clauseXMap, "not"); + ObjectFilter subfilter = parseFilterInternal(entry.getValue(), entry.getKey(), pcd, preliminaryParsingOnly, prismContext); if (preliminaryParsingOnly) { return null; } else { @@ -287,42 +257,65 @@ private static NotFilter parseNotFilter(XNode xnode, P } } - private static EqualFilter parseEqualFilter(XNode xnode, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ - LOGGER.trace("Start to parse EQUALS filter"); - MapXNode xmap = toMap(xnode); - ItemPath itemPath = getPath(xmap, prismContext); - + private static ObjectFilter parseComparisonFilter(QName clauseQName, MapXNode clauseXMap, + PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { + + boolean isEq = QNameUtil.match(clauseQName, CLAUSE_EQUAL); + boolean isGt = QNameUtil.match(clauseQName, CLAUSE_GREATER); + boolean isGtEq = QNameUtil.match(clauseQName, CLAUSE_GREATER_OR_EQUAL); + boolean isLt = QNameUtil.match(clauseQName, CLAUSE_LESS); + boolean isLtEq = QNameUtil.match(clauseQName, CLAUSE_LESS_OR_EQUAL); + + ItemPath itemPath = getPath(clauseXMap); if (itemPath == null || itemPath.isEmpty()){ throw new SchemaException("Could not convert query, because query does not contain item path."); } - - QName matchingRule = determineMatchingRule(xmap); - - if (itemPath.last() == null) { - throw new SchemaException("Cannot convert query, because query does not contain property path."); - } QName itemName = ItemPath.getName(itemPath.last()); - - XNode valueXnode = xmap.get(KEY_FILTER_VALUE); - + + QName matchingRule = getMatchingRule(clauseXMap); + + XNode valueXnode = clauseXMap.get(ELEMENT_VALUE); + ItemPath rightSidePath = getPath(clauseXMap, ELEMENT_RIGHT_HAND_SIDE_PATH); + ItemDefinition itemDefinition = locateItemDefinition(valueXnode, itemPath, pcd, prismContext); if (itemDefinition != null){ itemName = itemDefinition.getName(); } if (valueXnode != null) { - Item item = parseItem(valueXnode, itemName, itemDefinition, prismContext); - if (preliminaryParsingOnly) { - return null; + if (!isEq && item.getValues().size() != 1) { + throw new SchemaException("Expected exactly one value, got " + item.getValues().size() + " instead"); + } + if (preliminaryParsingOnly) { + return null; } else { - return EqualFilter.createEqual(itemPath, (PrismProperty) item, matchingRule); + if (isEq) { + return EqualFilter.createEqual(itemPath, (PrismProperty) item, matchingRule); + } + PrismPropertyValue propertyValue = (PrismPropertyValue) item.getValue(0); + if (isGt || isGtEq) { + return GreaterFilter.createGreater(itemPath, pcd, propertyValue, isGtEq); + } else { + return LessFilter.createLess(itemPath, pcd, propertyValue, isLtEq); + } } - + } else if (rightSidePath != null) { + if (preliminaryParsingOnly) { + return null; + } else { + ItemDefinition rightSideDefinition = pcd != null ? pcd.findItemDefinition(rightSidePath) : null; + if (isEq) { + return EqualFilter.createEqual(itemPath, (PrismPropertyDefinition) itemDefinition, matchingRule, rightSidePath, rightSideDefinition); + } else if (isGt || isGtEq) { + return GreaterFilter.createGreater(itemPath, (PrismPropertyDefinition) itemDefinition, rightSidePath, rightSideDefinition, isGtEq); + } else { + return LessFilter.createLess(itemPath, (PrismPropertyDefinition) itemDefinition, rightSidePath, rightSideDefinition, isLtEq); + } + } } else { - - Entry expressionEntry = xmap.getSingleEntryThatDoesNotMatch( - KEY_FILTER_VALUE, KEY_FILTER_EQUAL_MATCHING, KEY_FILTER_EQUAL_PATH); + Entry expressionEntry = clauseXMap.getSingleEntryThatDoesNotMatch( + ELEMENT_VALUE, ELEMENT_MATCHING, ELEMENT_PATH); if (expressionEntry != null) { PrismPropertyValue expressionPropertyValue = prismContext.getXnodeProcessor().parsePrismPropertyFromGlobalXNodeValue( expressionEntry, ParsingContext.createDefault()); @@ -331,24 +324,32 @@ private static EqualFilter parseEqualFilter(XNode } else { ExpressionWrapper expressionWrapper = new ExpressionWrapper(); expressionWrapper.setExpression(expressionPropertyValue.getValue()); - return EqualFilter.createEqual(itemPath, (PrismPropertyDefinition) itemDefinition, matchingRule, expressionWrapper); + if (isEq) { + return EqualFilter.createEqual(itemPath, (PrismPropertyDefinition) itemDefinition, matchingRule, expressionWrapper); + } else if (isGt || isGtEq) { + return GreaterFilter.createGreater(itemPath, (PrismPropertyDefinition) itemDefinition, expressionWrapper, isGtEq); + } else { + return LessFilter.createLess(itemPath, (PrismPropertyDefinition) itemDefinition, expressionWrapper, isLtEq); + } } } else { + if (!isEq) { + throw new SchemaException("Comparison filter (greater, less) requires at least one value expression."); + } if (preliminaryParsingOnly) { return null; } else { - return EqualFilter.createNullEqual(itemPath, (PrismPropertyDefinition) itemDefinition, matchingRule); + return EqualFilter.createNullEqual(itemPath, (PrismPropertyDefinition) itemDefinition, matchingRule); } } } - } - private static InOidFilter parseInOidFilter(XNode xnode, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ - - MapXNode xmap = toMap(xnode); + private static InOidFilter parseInOidFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ + + boolean considerOwner = Boolean.TRUE.equals(clauseXMap.getParsedPrimitiveValue(ELEMENT_CONSIDER_OWNER, DOMUtil.XSD_BOOLEAN)); - XNode valueXnode = xmap.get(KEY_FILTER_VALUE); + XNode valueXnode = clauseXMap.get(ELEMENT_VALUE); if (valueXnode != null) { List oids = new ArrayList<>(); if (valueXnode instanceof ListXNode) { @@ -364,101 +365,83 @@ private static InOidFilter parseInOidFilter(XNode xnode, PrismContainerDefinitio } else { throw new SchemaException("The OID was expected to be present as primitive or list XNode, instead it is: " + valueXnode); } - InOidFilter inOidFilter = InOidFilter.createInOid(oids); - return inOidFilter; - + return InOidFilter.createInOid(considerOwner, oids); } else { - - ExpressionWrapper expression = parseExpression(xmap, prismContext); + ExpressionWrapper expression = parseExpression(clauseXMap, prismContext); if (expression != null) { - InOidFilter inOidFilter = InOidFilter.createInOid(expression); - return inOidFilter; + return InOidFilter.createInOid(considerOwner, expression); } else { throw new SchemaException("InOid filter with no values nor expression"); } } } - private static TypeFilter parseTypeFilter(XNode xnode, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ - MapXNode xmap = toMap(xnode); - QName type = xmap.getParsedPrimitiveValue(KEY_FILTER_TYPE_TYPE, DOMUtil.XSD_QNAME); + private static TypeFilter parseTypeFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ + QName type = clauseXMap.getParsedPrimitiveValue(ELEMENT_TYPE, DOMUtil.XSD_QNAME); - XNode subXFilter = xmap.get(KEY_FILTER_TYPE_FILTER); - ObjectFilter subFilter = null; + XNode subXFilter = clauseXMap.get(ELEMENT_FILTER); PrismObjectDefinition def = prismContext.getSchemaRegistry().findObjectDefinitionByType(type); + ObjectFilter subFilter = null; if (subXFilter != null && subXFilter instanceof MapXNode) { - subFilter = parseFilter((MapXNode) subXFilter, def); + subFilter = parseFilterInternal((MapXNode) subXFilter, def, preliminaryParsingOnly, prismContext); } - if (preliminaryParsingOnly) { return null; } else { return new TypeFilter(type, subFilter); } } - - - private static RefFilter parseRefFilter(XNode xnode, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ - MapXNode xmap = toMap(xnode); - ItemPath itemPath = getPath(xmap, prismContext); - - if (itemPath == null || itemPath.isEmpty()){ - throw new SchemaException("Cannot convert query, because query does not contain property path."); + + private static ExistsFilter parseExistsFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ + ItemPath path = getPath(clauseXMap); + + XNode subXFilter = clauseXMap.get(ELEMENT_FILTER); + ObjectFilter subFilter = null; + PrismContainerDefinition subPcd = pcd != null ? pcd.findContainerDefinition(path) : null; + if (subXFilter != null && subXFilter instanceof MapXNode) { + subFilter = parseFilterInternal((MapXNode) subXFilter, subPcd, preliminaryParsingOnly, prismContext); } + if (preliminaryParsingOnly) { + return null; + } else { + return ExistsFilter.createExists(path, pcd, subFilter); + } + } + + private static RefFilter parseRefFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException{ + ItemPath itemPath = getPath(clauseXMap); - if (itemPath.last() == null){ + if (itemPath == null || itemPath.isEmpty()){ throw new SchemaException("Cannot convert query, because query does not contain property path."); } - QName itemName = ItemPath.getName(itemPath.last()); - ItemPath parentPath = itemPath.allExceptLast(); - if (parentPath.isEmpty()){ - parentPath = null; - } - + ItemDefinition itemDefinition = null; if (pcd != null) { - itemDefinition = pcd.findItemDefinition(itemPath); - if (itemDefinition == null) { + itemDefinition = pcd != null ? pcd.findItemDefinition(itemPath) : null; + if (itemDefinition == null && !preliminaryParsingOnly) { throw new SchemaException("No definition for item "+itemPath+" in "+pcd); } } - - XNode valueXnode = xmap.get(KEY_FILTER_VALUE); - if (valueXnode != null){ - + XNode valueXnode = clauseXMap.get(ELEMENT_VALUE); + if (valueXnode != null) { Item item = prismContext.getXnodeProcessor().parseItem(valueXnode, itemName, itemDefinition, ParsingContext.allowMissingRefTypes()); - - if (preliminaryParsingOnly) { - return null; - } - - PrismReference ref = (PrismReference)item; - - if (item.getValues().size() < 1 ) { - throw new IllegalStateException("No values to search specified for item " + itemName); - } - - ExpressionWrapper expressionWrapper = null; - // TODO implement expressions - don't forget preliminary mode! - - return RefFilter.createReferenceEqual(itemPath, ref, expressionWrapper); - + if (preliminaryParsingOnly) { + return null; + } + PrismReference ref = (PrismReference)item; + if (item.getValues().size() < 1) { + throw new IllegalStateException("No values to search specified for item " + itemName); + } + return RefFilter.createReferenceEqual(itemPath, ref, null); } else { - ExpressionWrapper expressionWrapper = parseExpression(xmap, prismContext); -// Entry expressionEntry = xmap.getSingleEntryThatDoesNotMatch( -// -// KEY_FILTER_VALUE, KEY_FILTER_EQUAL_MATCHING, KEY_FILTER_EQUAL_PATH); + ExpressionWrapper expressionWrapper = parseExpression(clauseXMap, prismContext); if (expressionWrapper != null) { -// PrismPropertyValue expressionPropertyValue = prismContext.getXnodeProcessor() -// .parsePrismPropertyFromGlobalXNodeValue(expressionEntry); if (preliminaryParsingOnly) { return null; } else { -// ExpressionWrapper expressionWrapper = new ExpressionWrapper(); -// expressionWrapper.setExpression(expressionPropertyValue.getValue()); return RefFilter.createReferenceEqual(itemPath, (PrismReferenceDefinition) itemDefinition, expressionWrapper); } @@ -466,19 +449,17 @@ private static RefFilter parseRefFilter(XNode xnode, P if (preliminaryParsingOnly) { return null; } else { -// ExpressionWrapper expressionWrapper = null; return RefFilter.createReferenceEqual(itemPath, (PrismReferenceDefinition) itemDefinition, expressionWrapper); } } } - } private static ExpressionWrapper parseExpression(MapXNode xmap, PrismContext prismContext) throws SchemaException { Entry expressionEntry = xmap.getSingleEntryThatDoesNotMatch( - KEY_FILTER_VALUE, KEY_FILTER_EQUAL_MATCHING, KEY_FILTER_EQUAL_PATH); + ELEMENT_VALUE, ELEMENT_MATCHING, ELEMENT_PATH); if (expressionEntry != null) { PrismPropertyValue expressionPropertyValue = prismContext.getXnodeProcessor() .parsePrismPropertyFromGlobalXNodeValue(expressionEntry, ParsingContext.createDefault()); @@ -491,35 +472,28 @@ private static ExpressionWrapper parseExpression(MapXNode xmap, PrismContext pri } - private static SubstringFilter parseSubstringFilter(XNode xnode, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) + private static SubstringFilter parseSubstringFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { - MapXNode xmap = toMap(xnode); - ItemPath itemPath = getPath(xmap, prismContext); + ItemPath itemPath = getPath(clauseXMap); if (itemPath == null || itemPath.isEmpty()){ throw new SchemaException("Could not convert query, because query does not contain item path."); } - - QName matchingRule = determineMatchingRule(xmap); - - if (itemPath.last() == null){ - throw new SchemaException("Cannot convert query, becasue query does not contian property path."); - } QName itemName = ItemPath.getName(itemPath.last()); - - - XNode valueXnode = xmap.get(KEY_FILTER_VALUE); + QName matchingRule = getMatchingRule(clauseXMap); + + XNode valueXnode = clauseXMap.get(ELEMENT_VALUE); ItemDefinition itemDefinition = locateItemDefinition(valueXnode, itemPath, pcd, prismContext); Item item = parseItem(valueXnode, itemName, itemDefinition, prismContext); - Boolean anchorStart = xmap.getParsedPrimitiveValue(KEY_FILTER_SUBSTRING_ANCHOR_START, DOMUtil.XSD_BOOLEAN); + Boolean anchorStart = clauseXMap.getParsedPrimitiveValue(ELEMENT_ANCHOR_START, DOMUtil.XSD_BOOLEAN); if (anchorStart == null) { anchorStart = false; } - Boolean anchorEnd = xmap.getParsedPrimitiveValue(KEY_FILTER_SUBSTRING_ANCHOR_END, DOMUtil.XSD_BOOLEAN); + Boolean anchorEnd = clauseXMap.getParsedPrimitiveValue(ELEMENT_ANCHOR_END, DOMUtil.XSD_BOOLEAN); if (anchorEnd == null) { anchorEnd = false; } @@ -531,10 +505,8 @@ private static SubstringFilter parseSubstringFilter(XN } } - private static OrgFilter parseOrgFilter(XNode xnode, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { - MapXNode xmap = toMap(xnode); - - if (Boolean.TRUE.equals(xmap.getParsedPrimitiveValue(KEY_FILTER_ORG_IS_ROOT, DOMUtil.XSD_BOOLEAN))) { + private static OrgFilter parseOrgFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) throws SchemaException { + if (Boolean.TRUE.equals(clauseXMap.getParsedPrimitiveValue(ELEMENT_IS_ROOT, DOMUtil.XSD_BOOLEAN))) { // TODO check if other content is present if (preliminaryParsingOnly) { return null; @@ -543,21 +515,19 @@ private static OrgFilter parseOrgFilter(XNode xnode, P } } - XNode xorgrefnode = xmap.get(KEY_FILTER_ORG_REF); + XNode xorgrefnode = clauseXMap.get(ELEMENT_ORG_REF); if (xorgrefnode == null) { throw new SchemaException("No organization reference defined in the search query."); } MapXNode xorgrefmap = toMap(xorgrefnode); - String orgOid = xorgrefmap.getParsedPrimitiveValue(KEY_FILTER_ORG_REF_OID, DOMUtil.XSD_STRING); + String orgOid = xorgrefmap.getParsedPrimitiveValue(ELEMENT_OID, DOMUtil.XSD_STRING); if (orgOid == null || StringUtils.isBlank(orgOid)) { throw new SchemaException("No oid attribute defined in the organization reference element."); } - XsdTypeMapper.getTypeFromClass(Scope.class); - - String scopeString = xorgrefmap.getParsedPrimitiveValue(KEY_FILTER_ORG_SCOPE, DOMUtil.XSD_STRING); // original (in my opinion incorrect) place + String scopeString = xorgrefmap.getParsedPrimitiveValue(ELEMENT_SCOPE, DOMUtil.XSD_STRING); // original (in my opinion incorrect) place if (scopeString == null) { - scopeString = xmap.getParsedPrimitiveValue(KEY_FILTER_ORG_SCOPE, DOMUtil.XSD_STRING); // here it is placed by the serializer + scopeString = clauseXMap.getParsedPrimitiveValue(ELEMENT_SCOPE, DOMUtil.XSD_STRING); // here it is placed by the serializer } Scope scope = scopeString != null ? Scope.valueOf(scopeString) : null; @@ -589,23 +559,23 @@ private static PrimitiveXNode toPrimitive(XNode xnode, XNode context) throws Sch return (PrimitiveXNode)xnode; } - private static ItemPath getPath(MapXNode xmap, PrismContext prismContext) throws SchemaException { - XNode xnode = xmap.get(KEY_FILTER_EQUAL_PATH); + private static ItemPath getPath(MapXNode clauseXMap) throws SchemaException { + return getPath(clauseXMap, ELEMENT_PATH); + } + + private static ItemPath getPath(MapXNode clauseXMap, QName key) throws SchemaException { + XNode xnode = clauseXMap.get(key); if (xnode == null) { return null; } if (!(xnode instanceof PrimitiveXNode)) { - throw new SchemaException("Expected that field "+KEY_FILTER_EQUAL_PATH+" will be primitive, but it is "+xnode.getDesc()); + throw new SchemaException("Expected that field "+key+" will be primitive, but it is "+xnode.getDesc()); } -// XNodeProcessor processor = PrismUtil.getXnodeProcessor(prismContext); -// return processor.parseAtomicValue(xnode, new PrismPropertyDefinition(ItemPathType.COMPLEX_TYPE, ItemPathType.COMPLEX_TYPE, prismContext)); -// return ipt.getItemPath(); - return xmap.getParsedPrimitiveValue(KEY_FILTER_EQUAL_PATH, ItemPath.XSD_TYPE); -// return itemPathType.getItemPath(); + return clauseXMap.getParsedPrimitiveValue(key, ItemPath.XSD_TYPE); } - private static QName determineMatchingRule(MapXNode xmap) throws SchemaException{ - String matchingRuleString = xmap.getParsedPrimitiveValue(KEY_FILTER_EQUAL_MATCHING, DOMUtil.XSD_STRING); + private static QName getMatchingRule(MapXNode xmap) throws SchemaException{ + String matchingRuleString = xmap.getParsedPrimitiveValue(ELEMENT_MATCHING, DOMUtil.XSD_STRING); if (StringUtils.isNotBlank(matchingRuleString)){ if (QNameUtil.isUri(matchingRuleString)) { return QNameUtil.uriToQName(matchingRuleString); @@ -633,7 +603,6 @@ private static Item parseItem(XNode valueXnode, QName itemName, ItemDefinition i } private static ItemDefinition locateItemDefinition(XNode valueXnode, ItemPath itemPath, PrismContainerDefinition pcd, PrismContext prismContext) throws SchemaException{ -// QName itemName = ItemPath.getName(itemPath.last()); // TODO why using only the last item name? It can be in a container different from 'pcd' ItemDefinition itemDefinition = null; if (pcd != null) { itemDefinition = pcd.findItemDefinition(itemPath); @@ -648,9 +617,6 @@ private static ItemDefinition locateItemDefinition(XNo return locateItemDefinition(valueXnode, rest, (PrismContainerDefinition) itemDefinition, prismContext); } } - // do not throw...it will be saved as raw.. -// if (itemDefinition == null){ -// throw new SchemaException("No definition for item "+itemPath+" in "+pcd); } } return itemDefinition; @@ -665,64 +631,55 @@ public static MapXNode serializeFilter(ObjectFilter filter, PrismContext prismCo return serializeFilter(filter, PrismUtil.getXnodeProcessor(prismContext).createSerializer()); } - public static MapXNode serializeFilter(ObjectFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ + private static MapXNode serializeFilter(ObjectFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ + // null or primitive filters if (filter == null) { return null; + } else if (filter instanceof AllFilter) { + return serializeAllFilter(); + } else if (filter instanceof NoneFilter) { + return serializeNoneFilter(); + } else if (filter instanceof UndefinedFilter) { + return serializeUndefinedFilter(); + } else if (filter instanceof EqualFilter + || filter instanceof GreaterFilter + || filter instanceof LessFilter) { + return serializeComparisonFilter((PropertyValueFilter) filter, xnodeSerializer); + } else if (filter instanceof SubstringFilter) { + return serializeSubstringFilter((SubstringFilter) filter, xnodeSerializer); + } else if (filter instanceof RefFilter) { + return serializeRefFilter((RefFilter) filter, xnodeSerializer); + } else if (filter instanceof OrgFilter) { + return serializeOrgFilter((OrgFilter) filter, xnodeSerializer); + } else if (filter instanceof InOidFilter) { + return serializeInOidFilter((InOidFilter) filter, xnodeSerializer); } - + + // complex filters if (filter instanceof AndFilter) { return serializeAndFilter((AndFilter) filter, xnodeSerializer); - } - if (filter instanceof OrFilter) { + } else if (filter instanceof OrFilter) { return serializeOrFilter((OrFilter) filter, xnodeSerializer); - } - if (filter instanceof NotFilter) { + } else if (filter instanceof NotFilter) { return serializeNotFilter((NotFilter) filter, xnodeSerializer); } - if (filter instanceof EqualFilter) { - return serializeEqualsFilter((EqualFilter) filter, xnodeSerializer); - } - if (filter instanceof RefFilter) { - return serializeRefFilter((RefFilter) filter, xnodeSerializer); - } - - if (filter instanceof SubstringFilter) { - return serializeSubstringFilter((SubstringFilter) filter, xnodeSerializer); - } - if (filter instanceof OrgFilter) { - return serializeOrgFilter((OrgFilter) filter, xnodeSerializer); - } - if (filter instanceof TypeFilter) { return serializeTypeFilter((TypeFilter) filter, xnodeSerializer); + } else if (filter instanceof ExistsFilter) { + return serializeExistsFilter((ExistsFilter) filter, xnodeSerializer); } - if (filter instanceof NoneFilter) { - return serializeNoneFilter((NoneFilter) filter, xnodeSerializer); - } - - if (filter instanceof AllFilter) { - return serializeAllFilter((AllFilter) filter, xnodeSerializer); - } - - if (filter instanceof InOidFilter) { - return serializeInOidFilter((InOidFilter) filter, xnodeSerializer); - } - throw new UnsupportedOperationException("Unsupported filter type: " + filter); } private static MapXNode serializeAndFilter(AndFilter filter, XNodeSerializer xnodeSerilizer) throws SchemaException{ - MapXNode map = new MapXNode(); - map.put(KEY_FILTER_AND, serializeNaryLogicalSubfilters(filter.getConditions(), xnodeSerilizer)); - return map; + return createFilter(CLAUSE_AND, serializeNaryLogicalSubfilters(filter.getConditions(), xnodeSerilizer)); } private static MapXNode serializeOrFilter(OrFilter filter, XNodeSerializer xnodeSerilizer) throws SchemaException{ - MapXNode map = new MapXNode(); - map.put(KEY_FILTER_OR, serializeNaryLogicalSubfilters(filter.getConditions(), xnodeSerilizer)); + MapXNode map = createFilter(CLAUSE_OR, serializeNaryLogicalSubfilters(filter.getConditions(), xnodeSerilizer)); return map; } @@ -736,61 +693,78 @@ private static MapXNode serializeNaryLogicalSubfilters(List object } private static MapXNode serializeNotFilter(NotFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ + return createFilter(CLAUSE_NOT, serializeFilter(filter.getFilter(), xnodeSerializer)); + } + + @NotNull + private static MapXNode createFilter(QName clauseNot, MapXNode value) { MapXNode map = new MapXNode(); - map.put(KEY_FILTER_NOT, serializeFilter(filter.getFilter(), xnodeSerializer)); + map.put(clauseNot, value); return map; } private static MapXNode serializeInOidFilter(InOidFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException { - MapXNode filterMap = new MapXNode(); - - MapXNode contentsMap = new MapXNode(); - + MapXNode clauseMap = new MapXNode(); if (filter.getOids() != null && !filter.getOids().isEmpty()) { ListXNode valuesNode = new ListXNode(); for (String oid : filter.getOids()) { XNode val = createPrimitiveXNode(oid, DOMUtil.XSD_STRING); valuesNode.add(val); } - contentsMap.put(KEY_FILTER_VALUE, valuesNode); + clauseMap.put(ELEMENT_VALUE, valuesNode); } else if (filter.getExpression() != null) { // TODO serialize expression } else { throw new SchemaException("InOid filter with no values nor expression"); } + if (filter.isConsiderOwner()) { + clauseMap.put(ELEMENT_CONSIDER_OWNER, new PrimitiveXNode<>(true)); + } - filterMap.put(KEY_FILTER_IN_OID, contentsMap); - return filterMap; + return createFilter(CLAUSE_IN_OID, clauseMap); } - private static MapXNode serializeEqualsFilter(EqualFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ + private static MapXNode serializeComparisonFilter(PropertyValueFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ MapXNode map = new MapXNode(); - map.put(KEY_FILTER_EQUAL, serializeValueFilter(filter, xnodeSerializer)); + QName clause; + if (filter instanceof EqualFilter) { + clause = CLAUSE_EQUAL; + } else if (filter instanceof GreaterFilter) { + clause = ((GreaterFilter) filter).isEquals() ? CLAUSE_GREATER_OR_EQUAL : CLAUSE_GREATER; + } else if (filter instanceof LessFilter) { + clause = ((LessFilter) filter).isEquals() ? CLAUSE_LESS_OR_EQUAL : CLAUSE_LESS; + } else { + throw new IllegalStateException(); + } + map.put(clause, serializeValueFilter(filter, xnodeSerializer)); return map; } private static MapXNode serializeValueFilter(PropertyValueFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException { MapXNode map = new MapXNode(); serializeMatchingRule(filter, map); - - serializePath(filter, map); + serializePath(map, filter.getFullPath(), filter); - ListXNode valuesNode = new ListXNode(); - List values = filter.getValues(); if (values != null) { + ListXNode valuesNode = new ListXNode(); for (T val : values) { if (val.getParent() == null) { val.setParent(filter); } - XNode valNode = null; - - valNode = xnodeSerializer.serializeItemValue(val, filter.getDefinition()); - + XNode valNode = xnodeSerializer.serializeItemValue(val, filter.getDefinition()); + if (filter instanceof RefFilter) { // TODO shouldn't we do this in all cases? + valNode.setExplicitTypeDeclaration(true); + if (valNode.getTypeQName() == null) { + valNode.setTypeQName(ObjectReferenceType.COMPLEX_TYPE); + } + } valuesNode.add(valNode); } - - map.put(KEY_FILTER_VALUE, valuesNode); + map.put(ELEMENT_VALUE, valuesNode); + } + if (filter.getRightHandSidePath() != null) { + map.put(ELEMENT_RIGHT_HAND_SIDE_PATH, createPrimitiveXNode(filter.getRightHandSidePath(), ItemPath.XSD_TYPE)); } ExpressionWrapper xexpression = filter.getExpression(); @@ -803,86 +777,83 @@ private static MapXNode serializeValueFilter(PropertyValu } private static MapXNode serializeRefFilter(RefFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException { - - MapXNode map = new MapXNode(); - - map.put(KEY_FILTER_REF, serializeValueFilter(filter, xnodeSerializer)); + MapXNode map = createFilter(CLAUSE_REF, serializeValueFilter(filter, xnodeSerializer)); return map; } private static MapXNode serializeSubstringFilter(SubstringFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ MapXNode map = new MapXNode(); - map.put(KEY_FILTER_SUBSTRING, serializeValueFilter(filter, xnodeSerializer)); + MapXNode content = serializeValueFilter(filter, xnodeSerializer); + if (filter.isAnchorStart()) { + content.put(ELEMENT_ANCHOR_START, new PrimitiveXNode<>(true)); + } + if (filter.isAnchorEnd()) { + content.put(ELEMENT_ANCHOR_END, new PrimitiveXNode<>(true)); + } + map.put(CLAUSE_SUBSTRING, content); return map; } - private static MapXNode serializeTypeFilter(TypeFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ - MapXNode map = new MapXNode(); - map.put(KEY_FILTER_TYPE_TYPE, createPrimitiveXNode(filter.getType(), DOMUtil.XSD_QNAME)); - - MapXNode subXFilter = null; + MapXNode content = new MapXNode(); + content.put(ELEMENT_TYPE, createPrimitiveXNode(filter.getType(), DOMUtil.XSD_QNAME)); if (filter.getFilter() != null){ - subXFilter = serializeFilter(filter.getFilter(), xnodeSerializer); - map.put(KEY_FILTER_TYPE_FILTER, subXFilter); + content.put(ELEMENT_FILTER, serializeFilter(filter.getFilter(), xnodeSerializer)); } - - MapXNode xtypeFilter= new MapXNode(); - xtypeFilter.put(KEY_FILTER_TYPE, map); - return xtypeFilter; - + return createFilter(CLAUSE_TYPE, content); } - - private static MapXNode serializeNoneFilter(NoneFilter filter, XNodeSerializer xnodeSerializer) { - MapXNode map = new MapXNode(); - map.put(KEY_FILTER_NONE_TYPE, new MapXNode()); - return map; + + private static MapXNode serializeExistsFilter(ExistsFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ + MapXNode content = new MapXNode(); + serializePath(content, filter.getFullPath(), filter); + if (filter.getFilter() != null){ + content.put(ELEMENT_FILTER, serializeFilter(filter.getFilter(), xnodeSerializer)); + } + return createFilter(CLAUSE_EXISTS, content); } - + private static MapXNode serializeOrgFilter(OrgFilter filter, XNodeSerializer xnodeSerializer) { MapXNode map = new MapXNode(); if (filter.getOrgRef() != null) { MapXNode orgRefMap = new MapXNode(); - orgRefMap.put(KEY_FILTER_ORG_REF_OID, createPrimitiveXNode(filter.getOrgRef().getOid(), DOMUtil.XSD_STRING)); - map.put(KEY_FILTER_ORG_REF, orgRefMap); + orgRefMap.put(ELEMENT_OID, createPrimitiveXNode(filter.getOrgRef().getOid(), DOMUtil.XSD_STRING)); + map.put(ELEMENT_ORG_REF, orgRefMap); } if (filter.getScope() != null) { - map.put(KEY_FILTER_ORG_SCOPE, createPrimitiveXNode(filter.getScope().name(), DOMUtil.XSD_STRING)); + map.put(ELEMENT_SCOPE, createPrimitiveXNode(filter.getScope().name(), DOMUtil.XSD_STRING)); } if (filter.isRoot()) { - map.put(KEY_FILTER_ORG_IS_ROOT, createPrimitiveXNode(Boolean.TRUE, DOMUtil.XSD_BOOLEAN)); + map.put(ELEMENT_IS_ROOT, createPrimitiveXNode(Boolean.TRUE, DOMUtil.XSD_BOOLEAN)); } - - MapXNode xtypeFilter= new MapXNode(); - xtypeFilter.put(KEY_FILTER_ORG, map); - return xtypeFilter; + + return createFilter(CLAUSE_ORG, map); } - - - - private static MapXNode serializeAllFilter(AllFilter filter, XNodeSerializer xnodeSerializer) throws SchemaException{ - MapXNode xtypeFilter= new MapXNode(); - xtypeFilter.put(KEY_FILTER_ALL, null); - return xtypeFilter; - + + private static MapXNode serializeAllFilter() { + return createFilter(CLAUSE_ALL, new MapXNode()); } - private static void serializeMatchingRule(ValueFilter filter, MapXNode map){ + private static MapXNode serializeNoneFilter() { + return createFilter(CLAUSE_NONE, new MapXNode()); + } + + private static MapXNode serializeUndefinedFilter() { + return createFilter(CLAUSE_UNDEFINED, new MapXNode()); + } + + private static void serializeMatchingRule(ValueFilter filter, MapXNode map) { if (filter.getMatchingRule() != null){ PrimitiveXNode matchingNode = createPrimitiveXNode(filter.getMatchingRule().getLocalPart(), DOMUtil.XSD_STRING); - map.put(KEY_FILTER_EQUAL_MATCHING, matchingNode); + map.put(ELEMENT_MATCHING, matchingNode); } - } - private static void serializePath(ValueFilter filter, MapXNode map) { - if (filter.getFullPath() == null){ - throw new IllegalStateException("Cannot serialize filter " + filter +" because it does not contain path"); + private static void serializePath(MapXNode map, ItemPath path, ObjectFilter filter) { + if (path == null) { + throw new IllegalStateException("Cannot serialize filter " + filter + " because it does not contain path"); } - PrimitiveXNode pathNode = createPrimitiveXNode(filter.getFullPath(), ItemPath.XSD_TYPE); - - map.put(KEY_FILTER_EQUAL_PATH, pathNode); + map.put(ELEMENT_PATH, createPrimitiveXNode(path, ItemPath.XSD_TYPE)); } private static XNode serializePropertyValue(PrismPropertyValue value, PrismPropertyDefinition definition, PrismBeanConverter beanConverter) throws SchemaException { @@ -897,12 +868,13 @@ private static XNode serializePropertyValue(PrismPropertyValue value, Pri } private static PrimitiveXNode createPrimitiveXNode(T val, QName type) { - PrimitiveXNode xprim = new PrimitiveXNode(); + PrimitiveXNode xprim = new PrimitiveXNode<>(); xprim.setValue(val, type); return xprim; } + // TODO what with this? [med] public static void revive (ObjectFilter filter, final PrismContext prismContext) throws SchemaException { // Visitor visitor = new Visitor() { // @Override @@ -933,6 +905,6 @@ public static void revive (ObjectFilter filter, final PrismContext prismContext) * @param prismContext */ public static void parseFilterPreliminarily(MapXNode xfilter, PrismContext prismContext) throws SchemaException { - parseFilterContainer(xfilter, null, true, prismContext); + parseFilterInternal(xfilter, null, true, prismContext); } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XPathHolder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XPathHolder.java index 0b10c92ede7..5e20711dce9 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XPathHolder.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/parser/XPathHolder.java @@ -29,7 +29,8 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import com.evolveum.midpoint.prism.path.IdItemPathSegment; +import com.evolveum.midpoint.prism.PrismConstants; +import com.evolveum.midpoint.prism.path.*; import com.evolveum.midpoint.util.QNameUtil; import org.apache.commons.lang.StringUtils; @@ -38,9 +39,6 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; -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.xml.GlobalDynamicNamespacePrefixMapper; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.exception.SystemException; @@ -109,7 +107,7 @@ public XPathHolder(String xpath, Node domNode) { */ private void parse(String xpath, Node domNode, Map namespaceMap) { - segments = new ArrayList(); + segments = new ArrayList<>(); absolute = false; if (".".equals(xpath)) { @@ -168,9 +166,17 @@ private void parse(String xpath, Node domNode, Map namespaceMap) } QName qname; if (qnameArray.length == 1 || qnameArray[1] == null || qnameArray[1].isEmpty()) { - // default namespace <= empty prefix - String namespace = findNamespace(null, domNode, namespaceMap); - qname = new QName(namespace, qnameArray[0]); + if (ParentPathSegment.SYMBOL.equals(qnameArray[0])) { + qname = ParentPathSegment.QNAME; + } else if (ObjectReferencePathSegment.SYMBOL.equals(qnameArray[0])) { + qname = ObjectReferencePathSegment.QNAME; + } else if (IdentifierPathSegment.SYMBOL.equals(qnameArray[0])) { + qname = IdentifierPathSegment.QNAME; + } else { + // default namespace <= empty prefix + String namespace = findNamespace(null, domNode, namespaceMap); + qname = new QName(namespace, qnameArray[0]); + } } else { String namespacePrefix = qnameArray[0]; String namespace = findNamespace(namespacePrefix, domNode, namespaceMap); @@ -258,15 +264,23 @@ public XPathHolder(QName... segmentQNames) { } public XPathHolder(ItemPath propertyPath) { - this.segments = new ArrayList(); + this.segments = new ArrayList<>(); for (ItemPathSegment segment: propertyPath.getSegments()) { - XPathSegment xsegment = null; + XPathSegment xsegment; if (segment instanceof NameItemPathSegment) { boolean variable = ((NameItemPathSegment) segment).isVariable(); xsegment = new XPathSegment(((NameItemPathSegment)segment).getName(), variable); } else if (segment instanceof IdItemPathSegment) { xsegment = new XPathSegment(idToString(((IdItemPathSegment) segment).getId())); - } + } else if (segment instanceof ObjectReferencePathSegment) { + xsegment = new XPathSegment(PrismConstants.T_OBJECT_REFERENCE, false); + } else if (segment instanceof ParentPathSegment) { + xsegment = new XPathSegment(PrismConstants.T_PARENT, false); + } else if (segment instanceof IdentifierPathSegment) { + xsegment = new XPathSegment(PrismConstants.T_ID, false); + } else { + throw new IllegalStateException("Unknown segment: " + segment); + } this.segments.add(xsegment); } this.explicitNamespaceDeclarations = propertyPath.getNamespaceMap(); @@ -343,7 +357,14 @@ private void addPureXpath(StringBuilder sb) { sb.append("$"); } QName qname = seg.getQName(); - if (!StringUtils.isEmpty(qname.getPrefix())) { + + if (ObjectReferencePathSegment.QNAME.equals(qname)) { + sb.append(ObjectReferencePathSegment.SYMBOL); + } else if (ParentPathSegment.QNAME.equals(qname)) { + sb.append(ParentPathSegment.SYMBOL); + } else if (IdentifierPathSegment.QNAME.equals(qname)) { + sb.append(IdentifierPathSegment.SYMBOL); + } else if (!StringUtils.isEmpty(qname.getPrefix())) { sb.append(qname.getPrefix() + ":" + qname.getLocalPart()); } else { if (StringUtils.isNotEmpty(qname.getNamespaceURI())) { @@ -435,7 +456,7 @@ public ItemPath toItemPath() { } else { QName qName = segment.getQName(); boolean variable = segment.isVariable(); - segments.add(new NameItemPathSegment(qName, variable)); + segments.add(ItemPath.createSegment(qName, variable)); } } ItemPath path = new ItemPath(segments); 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 index 46809c17912..6736f8dc432 100644 --- 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 @@ -16,6 +16,10 @@ package com.evolveum.midpoint.prism.path; +import com.evolveum.midpoint.prism.PrismConstants; + +import javax.xml.namespace.QName; + /** * Denotes identifier of the object or container (i.e. OID or container ID). * Currently supported only for sorting (not even for filtering!). @@ -24,7 +28,10 @@ */ public class IdentifierPathSegment extends ItemPathSegment { - @Override + public static final String SYMBOL = "#"; + public static final QName QNAME = PrismConstants.T_ID; + + @Override public boolean equivalent(Object obj) { return equals(obj); } @@ -36,6 +43,6 @@ public ItemPathSegment clone() { @Override public String toString() { - return "#"; + return SYMBOL; } } 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 d139f04feec..13818a6188a 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 @@ -87,12 +87,12 @@ public ItemPath(Object[] namesOrIds) { 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 if ("#".equals(name)) { - return PrismConstants.T_ID; + if (ParentPathSegment.SYMBOL.equals(name)) { + return ParentPathSegment.QNAME; + } else if (ObjectReferencePathSegment.SYMBOL.equals(name)) { + return ObjectReferencePathSegment.QNAME; + } else if (IdentifierPathSegment.SYMBOL.equals(name)) { + return IdentifierPathSegment.QNAME; } else { return new QName(name); } @@ -171,14 +171,18 @@ public static ItemPath subPath(ItemPath prefix, ItemPathSegment subSegment) { } private void add(QName qname) { - if (PrismConstants.T_PARENT.equals(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()); + this.segments.add(createSegment(qname, false)); + } + + public static ItemPathSegment createSegment(QName qname, boolean variable) { + if (ParentPathSegment.QNAME.equals(qname)) { + return new ParentPathSegment(); + } else if (ObjectReferencePathSegment.QNAME.equals(qname)) { + return new ObjectReferencePathSegment(); + } else if (IdentifierPathSegment.QNAME.equals(qname)) { + return new IdentifierPathSegment(); } else { - this.segments.add(new NameItemPathSegment(qname)); + return new NameItemPathSegment(qname, variable); } } @@ -586,6 +590,14 @@ public int hashCode() { return result; } + public boolean equals(Object obj, boolean exact) { + if (exact) { + return equals(obj); + } else { + return obj instanceof ItemPath && equivalent((ItemPath) obj); + } + } + /** * More strict version of ItemPath comparison. Does not use any normalization * nor approximate matching QNames via QNameUtil.match. 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 index 573f2e7f881..fff445d2fc5 100644 --- 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 @@ -16,6 +16,10 @@ package com.evolveum.midpoint.prism.path; +import com.evolveum.midpoint.prism.PrismConstants; + +import javax.xml.namespace.QName; + /** * Denotes referenced object, like "assignment/targetRef/@/name" (name of assignment's target object) * @@ -23,7 +27,10 @@ */ public class ObjectReferencePathSegment extends ReferencePathSegment { - @Override + public static final String SYMBOL = "@"; + public static final QName QNAME = PrismConstants.T_OBJECT_REFERENCE; + + @Override public boolean equivalent(Object obj) { return equals(obj); } @@ -35,6 +42,6 @@ public ItemPathSegment clone() { @Override public String toString() { - return "@"; + return SYMBOL; } } 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 index 642ebdecf2f..73176ec731f 100644 --- 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 @@ -16,6 +16,10 @@ package com.evolveum.midpoint.prism.path; +import com.evolveum.midpoint.prism.PrismConstants; + +import javax.xml.namespace.QName; + /** * Denotes parent object or container. * @@ -23,7 +27,10 @@ */ public class ParentPathSegment extends ReferencePathSegment { - @Override + public static final String SYMBOL = ".."; + public static final QName QNAME = PrismConstants.T_PARENT; + + @Override public boolean equivalent(Object obj) { return equals(obj); } @@ -35,6 +42,6 @@ public ItemPathSegment clone() { @Override public String toString() { - return ".."; + return SYMBOL; } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AllFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AllFilter.java index 2f1a4815579..91ab494d0dd 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AllFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AllFilter.java @@ -74,4 +74,13 @@ public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRul return true; } + @Override + public boolean equals(Object obj, boolean exact) { + return obj instanceof AllFilter; + } + + @Override + public int hashCode() { + return 0; + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AndFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AndFilter.java index 39022a794ae..641327bda3a 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AndFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/AndFilter.java @@ -106,4 +106,8 @@ public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRul return true; } + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof AndFilter; + } } 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 e32cde5be8b..b23aa70de19 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 @@ -74,24 +74,24 @@ static PrismPropertyValue createPropertyValue(PrismPropertyDefinition ite } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (equals ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) + public boolean equals(Object o, boolean exact) { + if (this == o) return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) + if (o == null || getClass() != o.getClass()) return false; - ComparativeFilter other = (ComparativeFilter) obj; - if (equals != other.equals) + if (!super.equals(o, exact)) return false; - return true; + + ComparativeFilter that = (ComparativeFilter) o; + + return equals == that.equals; + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (equals ? 1 : 0); + return result; } } 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 d32767f0d34..32955feecea 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 @@ -96,6 +96,16 @@ public static EqualFilter createEqual(ItemPath path, PrismPropertyDefinit List> pVals = createPropertyList(itemDefinition, realValue); return new EqualFilter(path, itemDefinition, matchingRule, pVals); } + + public static EqualFilter createEqualMultiple(ItemPath path, PrismPropertyDefinition itemDefinition, QName matchingRule, T... realValues) { + Validate.notNull(itemDefinition, "Item definition in the filter must not be null"); + Validate.notNull(path, "Path in the filter must not be null"); + if (realValues.length == 0 || (realValues.length == 1 && realValues[0] == null)) { + return createNullEqual(path, itemDefinition, matchingRule); + } + List> pVals = createPropertyListFromArray(itemDefinition, realValues); + return new EqualFilter(path, itemDefinition, matchingRule, pVals); + } public static EqualFilter createEqual(QName propertyName, PrismPropertyDefinition propertyDefinition, QName matchingRule, T realValue){ return createEqual(new ItemPath(propertyName), propertyDefinition, matchingRule, realValue); @@ -280,6 +290,11 @@ public List> getValues() { // TODO Auto-generated method stub return super.getValues(); } - + + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof EqualFilter; + } + } 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 92cd8e37a27..710ecf364bf 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 @@ -124,28 +124,7 @@ public String debugDump(int indent) { 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 + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("EXISTS("); @@ -163,4 +142,30 @@ public void accept(Visitor visitor) { visitor.visit(filter); } } + + @Override + public boolean equals(Object o, boolean exact) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ExistsFilter that = (ExistsFilter) o; + + if (fullPath != null ? !fullPath.equals(that.fullPath, exact) : that.fullPath != null) + return false; + if (exact) { + if (definition != null ? !definition.equals(that.definition) : that.definition != null) + return false; + } + return filter != null ? filter.equals(that.filter, exact) : that.filter == null; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (definition != null ? definition.hashCode() : 0); + result = 31 * result + (filter != null ? filter.hashCode() : 0); + return result; + } } 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 d0e64885063..02c6c8d7dd0 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 @@ -38,38 +38,38 @@ public class GreaterFilter extends ComparativeFilter { public GreaterFilter() { } - GreaterFilter(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals) { - super(parentPath, definition, value, equals); + GreaterFilter(ItemPath itemPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals) { + super(itemPath, definition, value, equals); } - GreaterFilter(ItemPath parentPath, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { - super(parentPath, definition, rightSidePath, rightSideDefinition, equals); + GreaterFilter(ItemPath itemPath, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + super(itemPath, definition, rightSidePath, rightSideDefinition, equals); } - public static GreaterFilter createGreater(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ - return new GreaterFilter(parentPath, definition, value, equals); + public static GreaterFilter createGreater(ItemPath itemPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ + return new GreaterFilter(itemPath, definition, value, equals); } - public static GreaterFilter createGreater(ItemPath parentPath, PrismContainerDefinition containerDef, + public static GreaterFilter createGreater(ItemPath itemPath, PrismContainerDefinition containerDef, PrismPropertyValue value, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); - return createGreater(parentPath, def, value, equals); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(itemPath, containerDef); + return createGreater(itemPath, def, value, equals); } - public static GreaterFilter createGreater(ItemPath parentPath, PrismPropertyDefinition itemDefinition, T realValue, boolean equals) throws SchemaException{ + public static GreaterFilter createGreater(ItemPath itemPath, PrismPropertyDefinition itemDefinition, T realValue, boolean equals) throws SchemaException{ PrismPropertyValue value = createPropertyValue(itemDefinition, realValue); if (value == null){ //TODO: create null } - return createGreater(parentPath, itemDefinition, value, equals); + return createGreater(itemPath, itemDefinition, value, equals); } - public static GreaterFilter createGreater(ItemPath parentPath, PrismContainerDefinition containerDef, + public static GreaterFilter createGreater(ItemPath itemPath, PrismContainerDefinition containerDef, T realValue, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); - return createGreater(parentPath, def, realValue, equals); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(itemPath, containerDef); + return createGreater(itemPath, def, realValue, equals); } public static GreaterFilter createGreater(QName propertyName, Class type, PrismContext prismContext, T realValue, boolean equals) @@ -84,6 +84,10 @@ public static GreaterFilter createGreater(ItemPath pat return createGreater(path, def, realValue, equals); } + + public static GreaterFilter createGreater(ItemPath propertyPath, PrismPropertyDefinition propertyDefinition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + return new GreaterFilter(propertyPath, propertyDefinition, rightSidePath, rightSideDefinition, equals); + } @Override public GreaterFilter clone() { @@ -140,4 +144,10 @@ public ItemPath getPath() { public static GreaterFilter createGreaterThanItem(ItemPath itemPath, PrismPropertyDefinition propertyDefinition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { return new GreaterFilter(itemPath, propertyDefinition, rightSidePath, rightSideDefinition, equals); } + + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof GreaterFilter; + } + } 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 fe8aa2e124d..4aa2217c8e4 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 @@ -26,6 +26,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.DebugUtil; +@Deprecated // deprecated because of confusing name/semantics; see https://wiki.evolveum.com/display/midPoint/Query+API+Evolution public class InFilter extends PropertyValueFilter { InFilter(ItemPath path, PrismPropertyDefinition definition, QName matchingRule, List values ) { @@ -104,5 +105,9 @@ public PrismPropertyDefinition getDefinition() { return (PrismPropertyDefinition) super.getDefinition(); } + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof InFilter; + } } 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 3a5f7eccfa3..75817db6348 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 @@ -35,15 +35,20 @@ public class InOidFilter extends ObjectFilter { private ExpressionWrapper expression; private boolean considerOwner; // temporary hack (checks owner OID) - InOidFilter(boolean considerOwner, Collection oids) { + private InOidFilter(boolean considerOwner, Collection oids) { this.considerOwner = considerOwner; this.oids = oids; } - InOidFilter(ExpressionWrapper expression){ + private InOidFilter(boolean considerOwner, ExpressionWrapper expression){ + this.considerOwner = considerOwner; this.expression = expression; } - + + public static InOidFilter createInOid(boolean considerOwner, Collection oids){ + return new InOidFilter(considerOwner, oids); + } + public static InOidFilter createInOid(Collection oids){ return new InOidFilter(false, oids); } @@ -60,8 +65,8 @@ public static InOidFilter createOwnerHasOidIn(String... oids){ return new InOidFilter(true, Arrays.asList(oids)); } - public static InOidFilter createInOid(ExpressionWrapper expression){ - return new InOidFilter(expression); + public static InOidFilter createInOid(boolean considerOwner, ExpressionWrapper expression){ + return new InOidFilter(considerOwner, expression); } public Collection getOids() { @@ -183,28 +188,27 @@ public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRul } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((oids == null) ? 0 : oids.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) + public boolean equals(Object o, boolean exact) { + if (this == o) return true; - if (obj == null) + if (o == null || getClass() != o.getClass()) return false; - if (getClass() != obj.getClass()) + + InOidFilter that = (InOidFilter) o; + + if (considerOwner != that.considerOwner) return false; - InOidFilter other = (InOidFilter) obj; - if (oids == null) { - if (other.oids != null) - return false; - } else if (!oids.equals(other.oids)) + if (oids != null ? !oids.equals(that.oids) : that.oids != null) return false; - return true; + return expression != null ? expression.equals(that.expression) : that.expression == null; + } + @Override + public int hashCode() { + int result = oids != null ? oids.hashCode() : 0; + result = 31 * result + (expression != null ? expression.hashCode() : 0); + result = 31 * result + (considerOwner ? 1 : 0); + return result; + } } 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 6e6ae02cde2..04eebf4ead9 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 @@ -24,7 +24,6 @@ import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; 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; @@ -34,55 +33,55 @@ public class LessFilter extends ComparativeFilter { - LessFilter(ItemPath parentPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals) { - super(parentPath, definition, value, equals); + LessFilter(ItemPath itemPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals) { + super(itemPath, definition, value, equals); } - LessFilter(ItemPath parentPath, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { - super(parentPath, definition, rightSidePath, rightSideDefinition, equals); + LessFilter(ItemPath itemPath, PrismPropertyDefinition definition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + super(itemPath, definition, rightSidePath, rightSideDefinition, equals); } public LessFilter() { } - 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(QName itemPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ + return new LessFilter(new ItemPath(itemPath), definition, value, 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 itemPath, PrismPropertyDefinition definition, PrismPropertyValue value, boolean equals){ + return new LessFilter(itemPath, definition, value, equals); } - public static LessFilter createLess(ItemPath parentPath, PrismContainerDefinition containerDef, + public static LessFilter createLess(ItemPath itemPath, PrismContainerDefinition containerDef, PrismPropertyValue value, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); - return createLess(parentPath, def, value, equals); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(itemPath, containerDef); + return createLess(itemPath, def, value, equals); } - public static LessFilter createLess(QName parentPath, PrismPropertyDefinition itemDefinition, T realValue, boolean equals) throws SchemaException{ - return createLess(new ItemPath(parentPath), itemDefinition, realValue, equals); + public static LessFilter createLess(QName itemPath, PrismPropertyDefinition itemDefinition, T realValue, boolean equals) throws SchemaException{ + return createLess(new ItemPath(itemPath), itemDefinition, realValue, equals); } - public static LessFilter createLess(ItemPath parentPath, PrismPropertyDefinition itemDefinition, T realValue, boolean equals) throws SchemaException{ + public static LessFilter createLess(ItemPath itemPath, PrismPropertyDefinition itemDefinition, T realValue, boolean equals) throws SchemaException{ PrismPropertyValue value = createPropertyValue(itemDefinition, realValue); if (value == null){ // create null filter } - return createLess(parentPath, itemDefinition, value, equals); + return createLess(itemPath, 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, + public static LessFilter createLess(ItemPath itemPath, PrismContainerDefinition containerDef, T realValue, boolean equals) throws SchemaException { - PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(parentPath, containerDef); - return createLess(parentPath, def, realValue, equals); + PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(itemPath, containerDef); + return createLess(itemPath, def, realValue, equals); } public static LessFilter createLess(QName propertyName, Class type, PrismContext prismContext, T realValue, boolean equals) @@ -96,7 +95,12 @@ public static LessFilter createLess(ItemPath path, Cla PrismPropertyDefinition def = (PrismPropertyDefinition) FilterUtils.findItemDefinition(path, type, prismContext); return createLess(path, def, realValue, equals); - } + } + + public static LessFilter createLess(ItemPath propertyPath, PrismPropertyDefinition propertyDefinition, ItemPath rightSidePath, ItemDefinition rightSideDefinition, boolean equals) { + return new LessFilter(propertyPath, propertyDefinition, rightSidePath, rightSideDefinition, equals); + } + @Override public LessFilter clone() { LessFilter clone = new LessFilter(getFullPath(), getDefinition(), getSingleValue(), isEquals()); @@ -149,4 +153,10 @@ public ItemPath getPath() { return getFullPath(); } + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof LessFilter; + } + + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LogicalFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LogicalFilter.java index d376996ab90..64fb4e82726 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LogicalFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LogicalFilter.java @@ -99,7 +99,7 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals(Object obj, boolean exact) { if (this == obj) return true; if (obj == null) @@ -107,11 +107,19 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; LogicalFilter other = (LogicalFilter) obj; - if (conditions == null) { - if (other.conditions != null) + + if (conditions != null) { + if (conditions.size() != other.conditions.size()) { return false; - } else if (!conditions.equals(other.conditions)) - return false; + } + for (int i = 0; i < conditions.size(); i++) { + ObjectFilter of1 = this.conditions.get(i); + ObjectFilter of2 = other.conditions.get(i); + if (!of1.equals(of2, exact)) { + return false; + } + } + } return true; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NoneFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NoneFilter.java index 62104cedce8..083e6b03bbe 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NoneFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NoneFilter.java @@ -73,4 +73,15 @@ public String toString() { public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException { return false; } + + @Override + public boolean equals(Object obj, boolean exact) { + return obj instanceof NoneFilter; + } + + @Override + public int hashCode() { + return 0; + } + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NotFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NotFilter.java index 5b1b51a174c..77321630c4f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NotFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/NotFilter.java @@ -90,4 +90,10 @@ public String toString() { public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRuleRegistry) throws SchemaException { return !getFilter().match(value, matchingRuleRegistry); } + + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof NotFilter; + } + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectFilter.java index d6b73902d99..f7994a4ce97 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ObjectFilter.java @@ -52,4 +52,6 @@ public void revive(final PrismContext prismContext) throws SchemaException { } public abstract void checkConsistence(); + + public abstract boolean equals(Object o, boolean exact); } 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 a22b26b266f..fa26e32b2aa 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 @@ -52,4 +52,30 @@ public OrderDirection getDirection() { public String toString() { return orderBy.toString() + " " + direction; } + + @Override + public boolean equals(Object o) { + return equals(o, true); + } + + public boolean equals(Object o, boolean exact) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ObjectOrdering that = (ObjectOrdering) o; + + if (orderBy != null ? !orderBy.equals(that.orderBy, exact) : that.orderBy != null) + return false; + return direction == that.direction; + + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (direction != null ? direction.hashCode() : 0); + return result; + } } 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 4708c9dc1c2..e48bb8b14e0 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 @@ -256,4 +256,48 @@ public String toString() { return sb.toString(); } + + @Override + public boolean equals(Object o) { + return equals(o, true); + } + + public boolean equals(Object o, boolean exact) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ObjectPaging that = (ObjectPaging) o; + + if (offset != null ? !offset.equals(that.offset) : that.offset != null) + return false; + if (maxSize != null ? !maxSize.equals(that.maxSize) : that.maxSize != null) + return false; + if ((ordering != null && that.ordering == null) || (ordering == null && that.ordering != null)) { + return false; + } + if (ordering != null) { + if (ordering.size() != that.ordering.size()) { + return false; + } + for (int i = 0; i < ordering.size(); i++) { + ObjectOrdering oo1 = this.ordering.get(i); + ObjectOrdering oo2 = that.ordering.get(i); + if (!oo1.equals(oo2, exact)) { + return false; + } + } + } + return cookie != null ? cookie.equals(that.cookie) : that.cookie == null; + } + + @Override + public int hashCode() { + int result = offset != null ? offset.hashCode() : 0; + result = 31 * result + (maxSize != null ? maxSize.hashCode() : 0); + result = 31 * result + (ordering != null ? ordering.hashCode() : 0); + result = 31 * result + (cookie != null ? cookie.hashCode() : 0); + return result; + } } 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 21a61e23048..f5cde569b33 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 @@ -208,4 +208,39 @@ public Integer getMaxSize() { } return paging.getMaxSize(); } + + public boolean equals(Object o) { + return equals(o, true); + } + + public boolean equivalent(Object o) { + return equals(o, false); + } + + public boolean equals(Object o, boolean exact) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + ObjectQuery that = (ObjectQuery) o; + + if (allowPartialResults != that.allowPartialResults) + return false; + if (useNewQueryInterpreter != that.useNewQueryInterpreter) + return false; + if (filter != null ? !filter.equals(that.filter, exact) : that.filter != null) + return false; + return paging != null ? paging.equals(that.paging, exact) : that.paging == null; + + } + + @Override + public int hashCode() { + int result = filter != null ? filter.hashCode() : 0; + result = 31 * result + (paging != null ? paging.hashCode() : 0); + result = 31 * result + (allowPartialResults ? 1 : 0); + result = 31 * result + (useNewQueryInterpreter ? 1 : 0); + return result; + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrFilter.java index 71edf0c1efe..137a40cda76 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrFilter.java @@ -99,4 +99,10 @@ public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRul } return false; } + + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof OrFilter; + } + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrgFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrgFilter.java index 7aced926976..cf38b456800 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrgFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/OrgFilter.java @@ -27,7 +27,7 @@ public class OrgFilter extends ObjectFilter { - public static enum Scope {ONE_LEVEL, SUBTREE} + public enum Scope {ONE_LEVEL, SUBTREE} private PrismReferenceValue baseOrgRef; private Scope scope; @@ -113,7 +113,7 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals(Object obj, boolean exact) { if (this == obj) return true; if (obj == null) 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 7c4f99b05b7..52f4babaeaf 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 @@ -17,7 +17,6 @@ package com.evolveum.midpoint.prism.query; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -25,40 +24,26 @@ import com.evolveum.midpoint.prism.PrismContainerValue; -import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; -import org.w3c.dom.Element; -import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.Itemable; -import com.evolveum.midpoint.prism.Objectable; -import com.evolveum.midpoint.prism.PrismConstants; -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.MatchingRule; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.util.PrismUtil; -import com.evolveum.midpoint.prism.xnode.MapXNode; -import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; public abstract class PropertyValueFilter extends ValueFilter implements Itemable { private ExpressionWrapper expression; private List values; - private ItemPath rightSidePath; // alternative to "values" - private ItemDefinition rightSideDefinition; // optional (needed only if path points to extension item) + private ItemPath rightHandSidePath; // alternative to "values" + private ItemDefinition rightHandSideDefinition; // optional (needed only if path points to extension item) /* * TODO clean up the right side path/definition mess @@ -68,11 +53,11 @@ public abstract class PropertyValueFilter extends ValueFil super(); } - PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, ItemPath rightSidePath, ItemDefinition rightSideDefinition) { + PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, ItemPath rightHandSidePath, ItemDefinition rightHandSideDefinition) { super(path, definition, matchingRule); - Validate.notNull(rightSidePath, "rightSidePath"); - this.rightSidePath = rightSidePath; - this.rightSideDefinition = rightSideDefinition; + Validate.notNull(rightHandSidePath, "rightHandSidePath"); + this.rightHandSidePath = rightHandSidePath; + this.rightHandSideDefinition = rightHandSideDefinition; } PropertyValueFilter(ItemPath path, ItemDefinition definition, QName matchingRule, List values) { @@ -127,7 +112,22 @@ static List> createPropertyList(PrismPropertyDefinitio return pValues; } - + + static List> createPropertyListFromArray(PrismPropertyDefinition itemDefinition, T... realValues) { + List> pVals = new ArrayList>(); + + for (T realValue : realValues) { + if (realValue instanceof PrismPropertyValue) { + PrismPropertyValue pVal = (PrismPropertyValue) realValue; + PrismUtil.recomputePrismPropertyValue(pVal, itemDefinition.getPrismContext()); + pVals.add(pVal); + } else { + pVals.add(new PrismPropertyValue<>(realValue)); + } + } + return pVals; + } + static List> createPropertyList(PrismPropertyDefinition itemDefinition, T realValue){ List> pVals = new ArrayList>(); @@ -138,6 +138,7 @@ static List> createPropertyList(PrismPropertyDefinitio PrismUtil.recomputePrismPropertyValue(pVal, itemDefinition.getPrismContext()); pVals.add(pVal); }else{ + // TODO what's this??? pVals.addAll(PrismPropertyValue.createCollection((Collection) realValue)); } } @@ -214,23 +215,23 @@ public Item getFilterItem() throws SchemaException{ return filterItem; } - public ItemPath getRightSidePath() { - return rightSidePath; + public ItemPath getRightHandSidePath() { + return rightHandSidePath; } - public ItemDefinition getRightSideDefinition() { - return rightSideDefinition; + public ItemDefinition getRightHandSideDefinition() { + return rightHandSideDefinition; } - public void setRightSidePath(ItemPath rightSidePath) { - this.rightSidePath = rightSidePath; - if (rightSidePath != null) { + public void setRightHandSidePath(ItemPath rightHandSidePath) { + this.rightHandSidePath = rightHandSidePath; + if (rightHandSidePath != null) { values = null; } } - public void setRightSideDefinition(ItemDefinition rightSideDefinition) { - this.rightSideDefinition = rightSideDefinition; + public void setRightHandSideDefinition(ItemDefinition rightHandSideDefinition) { + this.rightHandSideDefinition = rightHandSideDefinition; } public ExpressionWrapper getExpression() { @@ -286,36 +287,46 @@ public boolean match(PrismContainerValue cvalue, MatchingRuleRegistry matchingRu return true; } - + @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((expression == null) ? 0 : expression.hashCode()); - result = prime * result + ((values == null) ? 0 : values.hashCode()); - return result; + public boolean equals(Object o) { + return equals(o, true); } @Override - public boolean equals(Object obj) { - if (this == obj) + public boolean equals(Object o, boolean exact) { + if (this == o) return true; - if (obj == null) + if (o == null || getClass() != o.getClass()) return false; - if (getClass() != obj.getClass()) + if (!super.equals(o, exact)) return false; - PropertyValueFilter other = (PropertyValueFilter) obj; - if (expression == null) { - if (other.expression != null) - return false; - } else if (!expression.equals(other.expression)) + + PropertyValueFilter that = (PropertyValueFilter) o; + + if (expression != null ? !expression.equals(that.expression) : that.expression != null) return false; - if (values == null) { - if (other.values != null) - return false; - } else if (!values.equals(other.values)) + if (values != null ? !values.equals(that.values) : that.values != null) return false; - return true; + if (rightHandSidePath != null ? !rightHandSidePath.equals(that.rightHandSidePath, exact) : that.rightHandSidePath != null) + return false; + if (exact) { + return rightHandSideDefinition != null ? + rightHandSideDefinition.equals(that.rightHandSideDefinition) : + that.rightHandSideDefinition == null; + } else { + return true; + } + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (expression != null ? expression.hashCode() : 0); + result = 31 * result + (values != null ? values.hashCode() : 0); + result = 31 * result + (rightHandSidePath != null ? rightHandSidePath.hashCode() : 0); + result = 31 * result + (rightHandSideDefinition != null ? rightHandSideDefinition.hashCode() : 0); + return result; } public String debugDump(int indent, StringBuilder sb){ @@ -355,7 +366,7 @@ public String debugDump(int indent, StringBuilder sb){ sb.append(DebugUtil.debugDump(expression.getExpression(), indent + 2)); } - if (getRightSidePath() != null) { + if (getRightHandSidePath() != null) { sb.append("\n"); DebugUtil.indentDebugDump(sb, indent+1); sb.append("RIGHT SIDE PATH: "); @@ -363,8 +374,8 @@ public String debugDump(int indent, StringBuilder sb){ sb.append("\n"); DebugUtil.indentDebugDump(sb, indent+1); sb.append("RIGHT SIDE DEF: "); - if (getRightSideDefinition() != null) { - sb.append(getRightSideDefinition().toString()); + if (getRightHandSideDefinition() != null) { + sb.append(getRightHandSideDefinition().toString()); } else { sb.append("null"); } @@ -399,8 +410,8 @@ public String toString(StringBuilder sb){ } } } - if (rightSidePath != null) { - sb.append(getRightSidePath()); + if (rightHandSidePath != null) { + sb.append(getRightHandSidePath()); } return sb.toString(); } @@ -410,11 +421,11 @@ public String toString(StringBuilder sb){ public abstract PropertyValueFilter clone(); protected void copyRightSideThingsFrom(PropertyValueFilter original) { - if (original.getRightSidePath() != null) { - setRightSidePath(original.getRightSidePath()); + if (original.getRightHandSidePath() != null) { + setRightHandSidePath(original.getRightHandSidePath()); } - if (original.getRightSideDefinition() != null) { - setRightSideDefinition(original.getRightSideDefinition()); + if (original.getRightHandSideDefinition() != null) { + setRightHandSideDefinition(original.getRightHandSideDefinition()); } } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/QueryJaxbConvertor.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/QueryJaxbConvertor.java index 6cf3a29bf9b..4953ae4df06 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/QueryJaxbConvertor.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/QueryJaxbConvertor.java @@ -18,16 +18,10 @@ import javax.xml.namespace.QName; -import org.w3c.dom.Element; - -import com.evolveum.midpoint.prism.Objectable; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.parser.QueryConvertor; import com.evolveum.midpoint.prism.xnode.MapXNode; -import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.prism.xml.ns._public.query_3.PagingType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; @@ -54,7 +48,7 @@ public static ObjectQuery createTypeObjectQuery(QueryType queryType, PrismContex if (queryType.getFilter().containsFilterClause()){ MapXNode mapXnode = queryType.getFilter().getFilterClauseXNode(); - QName type = mapXnode.getParsedPrimitiveValue(QueryConvertor.KEY_FILTER_TYPE_TYPE, DOMUtil.XSD_QNAME); + QName type = mapXnode.getParsedPrimitiveValue(QueryConvertor.ELEMENT_TYPE, DOMUtil.XSD_QNAME); if (type == null){ throw new SchemaException("Query does not countain type filter. Cannot by parse."); } @@ -110,16 +104,16 @@ public static ObjectFilter createObjectFilter(PrismObject } } - public static ObjectQuery createObjectQueryInternal(Class clazz, SearchFilterType filterType, PagingType pagingType, PrismContext prismContext) + public static ObjectQuery createObjectQueryInternal(Class clazz, SearchFilterType filterType, PagingType pagingType, PrismContext prismContext) throws SchemaException { - PrismObjectDefinition objDef = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(clazz); + PrismContainerDefinition objDef = prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(clazz); if (objDef == null) { - throw new SchemaException("cannot find obj definition for class "+clazz); + throw new SchemaException("cannot find obj/container definition for class "+clazz); } return createObjectQueryInternal(objDef, filterType, pagingType, prismContext); } - public static ObjectQuery createObjectQueryInternal(PrismObjectDefinition objDef, SearchFilterType filterType, PagingType pagingType, PrismContext prismContext) + public static ObjectQuery createObjectQueryInternal(PrismContainerDefinition objDef, SearchFilterType filterType, PagingType pagingType, PrismContext prismContext) throws SchemaException { try { 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 97e89fdf43e..1e3b0ba865b 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 @@ -237,4 +237,10 @@ public PrismReferenceDefinition getDefinition() { // TODO Auto-generated method stub return (PrismReferenceDefinition) super.getDefinition(); } + + @Override + public boolean equals(Object obj, boolean exact) { + return super.equals(obj, exact) && obj instanceof RefFilter; + } + } 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 e6a7612e47d..eddc75caef9 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 @@ -124,7 +124,7 @@ public static SubstringFilter createSubstring(ItemPath path, PrismPropertyDe return createNullSubstring(path, itemDefinition, matchingRule); } List> pValues = createPropertyList(itemDefinition, realValues); - return new SubstringFilter(path, itemDefinition, matchingRule, pValues); + return new SubstringFilter(path, itemDefinition, matchingRule, pValues, anchorStart, anchorEnd); } public static SubstringFilter createSubstring(ItemPath path, PrismPropertyDefinition itemDefinition, QName matchingRule, PrismPropertyValue values) { @@ -236,7 +236,14 @@ public String debugDump(int indent) { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SUBSTRING: "); - return toString(sb); + String rv = toString(sb); + if (anchorStart) { + rv += ",S"; + } + if (anchorEnd) { + rv += ",E"; + } + return rv; } @Override @@ -297,4 +304,28 @@ public PrismPropertyDefinition getDefinition() { return (PrismPropertyDefinition) super.getDefinition(); } + @Override + public boolean equals(Object o, boolean exact) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o, exact)) + return false; + + SubstringFilter that = (SubstringFilter) o; + + if (anchorStart != that.anchorStart) + return false; + return anchorEnd == that.anchorEnd; + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (anchorStart ? 1 : 0); + result = 31 * result + (anchorEnd ? 1 : 0); + return result; + } } 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 ffa49c6b496..959949b5eda 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,13 +124,14 @@ public String debugDump(int indent) { } @Override - public boolean equals(Object o) { + public boolean equals(Object o, boolean exact) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TypeFilter that = (TypeFilter) o; if (type != null ? !type.equals(that.type) : that.type != null) return false; + if (filter != null ? !filter.equals(that.filter, exact) : that.filter != null) return false; return true; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/UndefinedFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/UndefinedFilter.java index 3cbffdc1532..29ef92a6701 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/UndefinedFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/UndefinedFilter.java @@ -49,4 +49,15 @@ public boolean match(PrismContainerValue value, MatchingRuleRegistry matchingRul return true; } + @Override + public boolean equals(Object obj, boolean exact) { + return obj instanceof UndefinedFilter; + } + + @Override + public int hashCode() { + return 0; + } + + } 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 b3ebd1c9ab5..d2f53710a5f 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 @@ -149,7 +149,7 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals(Object obj, boolean exact) { if (this == obj) return true; if (obj == null) @@ -157,15 +157,17 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; ValueFilter other = (ValueFilter) obj; - if (definition == null) { - if (other.definition != null) + if (exact) { + if (definition == null) { + if (other.definition != null) + return false; + } else if (!definition.equals(other.definition)) return false; - } else if (!definition.equals(other.definition)) - return false; + } if (fullPath == null) { if (other.fullPath != null) return false; - } else if (!fullPath.equivalent(other.fullPath)) // TODO: ok? + } else if (!fullPath.equals(other.fullPath, exact)) return false; if (matchingRule == null) { if (other.matchingRule != null) 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 e1146eab0e7..ba778c7ae03 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 @@ -104,14 +104,14 @@ public S_AtomicFilterExit item(ItemPath itemPath, ItemDefinition itemDefinition) throw new IllegalStateException("item() call with no filter"); } PropertyValueFilter newFilter = filter.clone(); - newFilter.setRightSidePath(itemPath); - newFilter.setRightSideDefinition(itemDefinition); + newFilter.setRightHandSidePath(itemPath); + newFilter.setRightHandSideDefinition(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)); + public S_MatchingRuleEntry eq(Object... values) { + return new R_AtomicFilter(this, EqualFilter.createEqualMultiple(itemPath, propertyDefinition, null, values)); } @Override @@ -165,21 +165,36 @@ public S_RightHandItemEntry le() { } @Override - public S_MatchingRuleEntry startsWith(String value) { + public S_MatchingRuleEntry startsWith(Object value) { return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, null, value, true, false)); } - @Override - public S_MatchingRuleEntry endsWith(String value) { + @Override + public S_MatchingRuleEntry startsWithPoly(String orig, String norm) { + return startsWith(new PolyString(orig, norm)); + } + + @Override + public S_MatchingRuleEntry endsWith(Object value) { return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, null, value, false, true)); } + @Override + public S_MatchingRuleEntry endsWithPoly(String orig, String norm) { + return endsWith(new PolyString(orig, norm)); + } + @Override - public S_MatchingRuleEntry contains(String value) { + public S_MatchingRuleEntry contains(Object value) { return new R_AtomicFilter(this, SubstringFilter.createSubstring(itemPath, propertyDefinition, null, value, false, false)); } - @Override + @Override + public S_MatchingRuleEntry containsPoly(String orig, String norm) { + return contains(new PolyString(orig, norm)); + } + + @Override public S_AtomicFilterExit ref(PrismReferenceValue value) { return new R_AtomicFilter(this, RefFilter.createReferenceEqual(itemPath, referenceDefinition, value)); } 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 0ed9150e5dd..c71cb71d37e 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 @@ -26,7 +26,7 @@ * @author mederly */ public interface S_ConditionEntry { - S_MatchingRuleEntry eq(Object value); + S_MatchingRuleEntry eq(Object... values); S_RightHandItemEntry eq(); S_MatchingRuleEntry eqPoly(String orig, String norm); S_MatchingRuleEntry gt(Object value) throws SchemaException; @@ -37,9 +37,12 @@ public interface S_ConditionEntry { S_RightHandItemEntry lt(); S_MatchingRuleEntry le(Object value) throws SchemaException; S_RightHandItemEntry le(); - S_AtomicFilterExit startsWith(String value); - S_AtomicFilterExit endsWith(String value); - S_AtomicFilterExit contains(String value); + S_MatchingRuleEntry startsWith(Object value); + S_MatchingRuleEntry startsWithPoly(String orig, String norm); + S_MatchingRuleEntry endsWith(Object value); + S_MatchingRuleEntry endsWithPoly(String orig, String norm); + S_MatchingRuleEntry contains(Object value); + S_MatchingRuleEntry containsPoly(String orig, String norm); S_AtomicFilterExit ref(PrismReferenceValue value); S_AtomicFilterExit ref(Collection values); // not supported by repo QueryInterpreter yet S_AtomicFilterExit ref(String oid); 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 e9c80e19aaa..204a2d34f28 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 @@ -46,6 +46,7 @@ import org.apache.xml.resolver.Catalog; import org.apache.xml.resolver.CatalogManager; import org.apache.xml.resolver.tools.CatalogResolver; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -656,14 +657,42 @@ public QName qualifyTypeName(QName typeName) throws SchemaException { return resolveUnqualifiedTypeName(typeName); } - public ComplexTypeDefinition determineParentDefinition(ComplexTypeDefinition complexTypeDefinition, ItemPath rest) { - 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); + // current implementation tries to find all references to the child CTD and select those that are able to resolve path of 'rest' + // fails on ambiguity + // it's a bit fragile, as adding new references to child CTD in future may break existing code + public ComplexTypeDefinition determineParentDefinition(@NotNull ComplexTypeDefinition child, @NotNull ItemPath rest) { + ComplexTypeDefinition parent = null; + for (PrismSchema schema : getSchemas()) { + if (schema == null) { + continue; + } + for (ComplexTypeDefinition ctd : schema.getComplexTypeDefinitions()) { + for (ItemDefinition item : ctd.getDefinitions()) { + if (item instanceof PrismContainerDefinition) { + PrismContainerDefinition itemPcd = (PrismContainerDefinition) item; + if (itemPcd.getComplexTypeDefinition() != null) { + if (child.getTypeName().equals(itemPcd.getComplexTypeDefinition().getTypeName())) { + if (!rest.isEmpty() && ctd.findItemDefinition(rest) == null) { + continue; + } + if (parent != null && !parent.getTypeClass().equals(ctd.getTypeName())) { + throw new IllegalStateException("Couldn't find parent definition for " + child.getTypeName() + ": More than one candidate found: " + + parent.getTypeName() + ", " + itemPcd.getTypeName()); + } + parent = ctd; + } + } + } + } + } } - return def; +// ComplexTypeDefinition def = findComplexTypeDefinition(new QName( +// "http://midpoint.evolveum.com/xml/ns/public/common/common-3", +// "ObjectType")); // FIXME BRUTAL HACK + if (parent == null) { + throw new IllegalStateException("Couldn't find definition for parent for " + child.getTypeName() + ", path=" + rest); + } + return parent; } public PrismObjectDefinition determineReferencedObjectDefinition(QName targetTypeName, ItemPath rest) { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismTestUtil.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismTestUtil.java index 75847db5fd8..5fce52527af 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismTestUtil.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismTestUtil.java @@ -224,6 +224,16 @@ public static void displayQuery(ObjectQuery query) { } } + public static void displayQueryXml(String xml) { + LOGGER.trace("object query XML:\n{}", xml); + System.out.println("object query XML:\n" + xml); + } + + public static void displayText(String text) { + LOGGER.trace(text); + System.out.println(text); + } + public static void displayQueryType(QueryType queryType) throws SchemaException { displaySearchFilterType(queryType.getFilter()); } diff --git a/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ObjectReferenceType.java b/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ObjectReferenceType.java index 19ddcbac74f..6f5a51631d2 100644 --- a/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ObjectReferenceType.java +++ b/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ObjectReferenceType.java @@ -41,40 +41,8 @@ /** - * - * Reference to an object. It contains OID of the object that it refers to. - * - * - *

Java class for ObjectReferenceType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="ObjectReferenceType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *         <element name="filter" minOccurs="0">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <sequence>
- *                   <any processContents='lax' maxOccurs="unbounded" minOccurs="0"/>
- *                 </sequence>
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *       </sequence>
- *       <attribute name="oid" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}QName" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * + * TODO update this class by adding missing features (targetName, oid, type, relation). + * However, it's quite unclear if it's really necessary. */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "ObjectReferenceType", propOrder = { diff --git a/infra/prism/src/main/resources/xml/ns/public/query-3.xsd b/infra/prism/src/main/resources/xml/ns/public/query-3.xsd index 68dfe08fe2d..a22cd56f968 100644 --- a/infra/prism/src/main/resources/xml/ns/public/query-3.xsd +++ b/infra/prism/src/main/resources/xml/ns/public/query-3.xsd @@ -66,26 +66,20 @@ - + - - - + + TODO + - - - - Property which specifies matching rules. E.g. for polyString, - matching rules can be: norm, orig, strict etc. - - - + + + - - - + + @@ -165,21 +159,6 @@ - - - - - - TODO - - - - - - - - - @@ -192,38 +171,83 @@ - - - - - - - - - + + + + + + + + + + + Property which specifies matching rules. E.g. for polyString, + matching rules can be: norm, orig, strict etc. + + + + + - + - - - - XPath to the XML element for the queried property. - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + An item that is to be related to the left-hand-side one. + + + @@ -252,12 +276,17 @@ - + The elements and values of queried properties. - Multi-valued properties are not allowed here. - Use "and" or "or" clauses if needed. + + + + + + + An item that is to be related to the left-hand-side one. @@ -275,7 +304,21 @@ - + + + + + + + + + + + + + @@ -296,6 +339,13 @@ + + + + If true, queries not objects with a given OID/ID, but objects that have an owner with given OID/ID. + + + @@ -310,38 +360,77 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + Object being considered can reside anywhere in the subtree rooted at base org. + + + + + + + Object being considered has to reside one level below base org. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XPath to the XML element for the queried property. + + + + + @@ -364,15 +453,20 @@ - + - - - + + + + + + + + diff --git a/infra/prism/src/main/resources/xml/ns/public/types-3.xsd b/infra/prism/src/main/resources/xml/ns/public/types-3.xsd index 44d4c621372..c3391bf78b5 100644 --- a/infra/prism/src/main/resources/xml/ns/public/types-3.xsd +++ b/infra/prism/src/main/resources/xml/ns/public/types-3.xsd @@ -347,6 +347,18 @@ + + + +

+ The relation or a "role" of this reference. It may further specify + the meaning of the reference. E.g. it may specify whether the objects + linked by the reference are analogous, form a composition, aggregation, + are mebers of the org or managers of the org, etc. +

+
+
+
diff --git a/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestDelta.java b/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestDelta.java index 14dcf180a66..faec3af9b62 100644 --- a/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestDelta.java +++ b/infra/prism/src/test/java/com/evolveum/midpoint/prism/TestDelta.java @@ -24,7 +24,6 @@ import java.util.Collection; import com.evolveum.midpoint.prism.delta.*; -import com.evolveum.prism.xml.ns._public.types_3.ObjectReferenceType; import org.testng.AssertJUnit; import org.testng.annotations.BeforeSuite; diff --git a/infra/schema/pom.xml b/infra/schema/pom.xml index 89ba161919e..e81b0d2efea 100644 --- a/infra/schema/pom.xml +++ b/infra/schema/pom.xml @@ -105,6 +105,21 @@ 3.4-SNAPSHOT test
+ + org.xmlunit + xmlunit-core + test + + + org.xmlunit + xmlunit-legacy + test + + + commons-io + commons-io + test + diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java index 7286b0c702d..ff298ec0f62 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java @@ -16,70 +16,46 @@ package com.evolveum.midpoint.schema; -import static com.evolveum.midpoint.prism.util.PrismTestUtil.*; -import static org.testng.AssertJUnit.*; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.parser.DomParser; +import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.parser.QueryConvertor; -import com.evolveum.midpoint.prism.query.OrgFilter; -import com.evolveum.midpoint.prism.query.builder.QueryBuilder; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.util.PrismUtil; - -import com.evolveum.midpoint.prism.xnode.RootXNode; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; -import org.apache.commons.lang.StringUtils; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import com.evolveum.midpoint.prism.PrismConstants; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; -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.AndFilter; -import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.LogicalFilter; -import com.evolveum.midpoint.prism.query.NaryLogicalFilter; -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.QueryJaxbConvertor; -import com.evolveum.midpoint.prism.query.RefFilter; -import com.evolveum.midpoint.prism.query.TypeFilter; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.query.*; +import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.xnode.ListXNode; import com.evolveum.midpoint.prism.xnode.MapXNode; import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.DomAsserts; 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.ConnectorType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FailedOperationTypeType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GenericObjectType; -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.ShadowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.query_3.PagingType; 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.PolyStringType; +import org.apache.commons.io.FileUtils; +import org.custommonkey.xmlunit.XMLAssert; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.xml.namespace.QName; +import java.io.File; +import java.io.IOException; +import java.util.List; + +import static com.evolveum.midpoint.prism.PrismConstants.T_PARENT; +import static com.evolveum.midpoint.prism.util.PrismTestUtil.*; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType.F_OWNER_REF; +import static org.testng.AssertJUnit.*; public class TestQueryConvertor { @@ -335,6 +311,14 @@ private QueryType toQueryType(ObjectQuery query) throws Exception { return QueryJaxbConvertor.createQueryType(query, getPrismContext()); } + private QueryType toQueryType(String xml) throws SchemaException { + return PrismTestUtil.parseAtomicValue(xml, QueryType.COMPLEX_TYPE); + } + + private String toXml(QueryType q1jaxb) throws SchemaException { + return getPrismContext().serializeAtomicValue(q1jaxb, SchemaConstantsGenerated.Q_QUERY, PrismContext.LANG_XML); + } + @Test public void testGenericQuery() throws Exception { displayTestTitle("testGenericQuery"); @@ -417,118 +401,279 @@ public void testConvertQueryNullFilter() throws Exception { } - @Test - public void test100OrgFilterRoot() throws Exception { - displayTestTitle("test100OrgFilterRoot"); - - ObjectQuery query = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isRoot().build(); - String expected = " true "; + private void checkQuery(Class objectClass, ObjectQuery q1object, String q2xml) throws Exception { + // step 1 (serialization of Q1 + comparison) + displayText("Query 1:"); + displayQuery(q1object); + QueryType q1jaxb = toQueryType(q1object); + displayQueryType(q1jaxb); + String q1xml = toXml(q1jaxb); + displayQueryXml(q1xml); + XMLAssert.assertXMLEqual("Serialized query is not correct: Expected:\n" + q2xml + "\n\nReal:\n" + q1xml, q2xml, q1xml); + + // step 2 (parsing of Q2 + comparison) + displayText("Query 2:"); + displayQueryXml(q2xml); + QueryType q2jaxb = toQueryType(q2xml); + displayQueryType(q2jaxb); + ObjectQuery q2object = toObjectQuery(objectClass, q2jaxb); + assertEquals("Reparsed query is not as original one (via toString)", q1object.toString(), q2object.toString()); // primitive way of comparing parsed queries + assertTrue("Reparsed query is not as original one (via equivalent):\nq1="+q1object+"\nq2="+q2object, q1object.equivalent(q2object)); + } - checkQuery(query, expected); + private void checkQueryRoundtrip(Class objectClass, ObjectQuery q1object, String q2xml) throws Exception { + checkQuery(objectClass, q1object, q2xml); + String q1xml = toXml(toQueryType(q1object)); + ObjectQuery q2object = toObjectQuery(objectClass, toQueryType(q2xml)); + checkQuery(objectClass, q2object, q1xml); } - protected void checkQuery(ObjectQuery query, String expected) throws Exception { - displayQuery(query); + private void checkQueryRoundtripFile(Class objectClass, ObjectQuery query, String testName) throws Exception { + String fileName = TEST_DIR + "/" + testName + ".xml"; + checkQueryRoundtrip(objectClass, query, FileUtils.readFileToString(new File(fileName))); + } - QueryType queryType = toQueryType(query); - displayQueryType(queryType); + @Test + public void test100All() throws Exception { + final String TEST_NAME = "test100All"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()).all().build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - assertXml(queryType, expected); + @Test + public void test110None() throws Exception { + final String TEST_NAME = "test110None"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()).none().build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - ObjectQuery query2 = toObjectQuery(OrgType.class, queryType); - displayQuery(query2); + @Test + public void test120Undefined() throws Exception { + final String TEST_NAME = "test120Undefined"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()).undefined().build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - // primitive way of comparing queries - assertEquals("Reparsed query is not as original one", query.toString(), query2.toString()); + @Test + public void test200Equal() throws Exception { + final String TEST_NAME = "test200Equal"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_NAME).eqPoly("some-name", "somename").matchingOrig() + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - QueryType queryType2 = toQueryType(query2); - displayQueryType(queryType2); + @Test + public void test210EqualMultiple() throws Exception { + final String TEST_NAME = "test210EqualMultiple"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_EMPLOYEE_TYPE).eq("STD", "TEMP") + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - assertEquals("Reserialized query type is not as original one", queryType, queryType2); + @Test + public void test220EqualRightHandItem() throws Exception { + final String TEST_NAME = "test220EqualRightHandItem"; + displayTestTitle(TEST_NAME); + PrismObjectDefinition userDef = getPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(UserType.class); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_EMPLOYEE_NUMBER).eq().item(new ItemPath(UserType.F_COST_CENTER), userDef.findItemDefinition(UserType.F_COST_CENTER)) + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); } @Test - public void test110OrgFilterSubtree() throws Exception { - displayTestTitle("test110OrgFilterSubtree"); + public void test300Greater() throws Exception { + final String TEST_NAME = "test300Greater"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_COST_CENTER).gt("100000") + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - ObjectQuery query = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isChildOf("111").build(); - displayQuery(query); + @Test + public void test310AllComparisons() throws Exception { + final String TEST_NAME = "test310AllComparisons"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_COST_CENTER).gt("100000") + .and().item(UserType.F_COST_CENTER).lt("999999") + .or() + .item(UserType.F_COST_CENTER).ge("X100") + .and().item(UserType.F_COST_CENTER).le("X999") + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - String expected = "\n" + - " \n" + - " 111\n" + - " \n" + - " SUBTREE\n" + - " "; + @Test + public void test350Substring() throws Exception { + final String TEST_NAME = "test350Substring"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .item(UserType.F_EMPLOYEE_TYPE).contains("A") + .or().item(UserType.F_EMPLOYEE_TYPE).startsWith("B") + .or().item(UserType.F_EMPLOYEE_TYPE).endsWith("C") + .or().item(UserType.F_NAME).startsWithPoly("john", "john").matchingOrig() + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - checkQuery(query, expected); + @Test + public void test360Ref() throws Exception { + final String TEST_NAME = "test360Ref"; + displayTestTitle(TEST_NAME); + + // we test only parsing here, as there are more serialized forms used here + ObjectQuery q1object = QueryBuilder.queryFor(ShadowType.class, getPrismContext()) + .item(ShadowType.F_RESOURCE_REF).ref("oid1") + .or().item(ShadowType.F_RESOURCE_REF).ref("oid2", ResourceType.COMPLEX_TYPE) + .or().item(ShadowType.F_RESOURCE_REF).ref("oid3") + .or().item(ShadowType.F_RESOURCE_REF).ref("oid4", ResourceType.COMPLEX_TYPE) + .build(); + String q2xml = FileUtils.readFileToString(new File(TEST_DIR + "/" + TEST_NAME + ".xml")); + displayQueryXml(q2xml); + QueryType q2jaxb = toQueryType(q2xml); + displayQueryType(q2jaxb); + ObjectQuery q2object = toObjectQuery(ShadowType.class, q2jaxb); + assertEquals("Reparsed query is not as original one (via toString)", q1object.toString(), q2object.toString()); // primitive way of comparing parsed queries + assertTrue("Reparsed query is not as original one (via equivalent):\nq1="+q1object+"\nq2="+q2object, q1object.equivalent(q2object)); } @Test - public void test120OrgFilterDirect() throws Exception { - displayTestTitle("test120OrgFilterDirect"); + public void test365RefTwoWay() throws Exception { + final String TEST_NAME = "test365RefTwoWay"; + displayTestTitle(TEST_NAME); + PrismReferenceValue reference3 = new PrismReferenceValue("oid3", ResourceType.COMPLEX_TYPE); + reference3.setRelation(new QName("test")); + ObjectQuery q = QueryBuilder.queryFor(ShadowType.class, getPrismContext()) + .item(ShadowType.F_RESOURCE_REF).ref("oid1") + .or().item(ShadowType.F_RESOURCE_REF).ref("oid2", ResourceType.COMPLEX_TYPE) + .or().item(ShadowType.F_RESOURCE_REF).ref(reference3) + .build(); + checkQueryRoundtripFile(ShadowType.class, q, TEST_NAME); + } - ObjectQuery query = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isDirectChildOf("222").build(); - displayQuery(query); + @Test + public void test400OrgFilterRoot() throws Exception { + final String TEST_NAME = "test400OrgFilterRoot"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isRoot().build(); + checkQueryRoundtripFile(OrgType.class, q, TEST_NAME); + } - String expected = "\n" + - " \n" + - " 222\n" + - " \n" + - " ONE_LEVEL\n" + - " "; + @Test + public void test410OrgFilterSubtree() throws Exception { + final String TEST_NAME = "test410OrgFilterSubtree"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isChildOf("111").build(); + checkQueryRoundtripFile(OrgType.class, q, TEST_NAME); + } - checkQuery(query, expected); + @Test + public void test420OrgFilterDirect() throws Exception { + final String TEST_NAME = "test420OrgFilterDirect"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isDirectChildOf("222").build(); + checkQueryRoundtripFile(OrgType.class, q, TEST_NAME); } @Test - public void test130OrgFilterDefaultScope() throws Exception { - displayTestTitle("test130OrgFilterDefaultScope"); + public void test430OrgFilterDefaultScope() throws Exception { + final String TEST_NAME = "test430OrgFilterDefaultScope"; + displayTestTitle(TEST_NAME); - String filterText = "\n" + + // default scope is SUBTREE + String queryXml = "\n" + " \n" + " 333\n" + " \n" + - " "; - - SearchFilterType filterType = getPrismContext().parseAtomicValue(filterText, SearchFilterType.COMPLEX_TYPE, PrismContext.LANG_XML); - displaySearchFilterType(filterType); - - ObjectFilter filter = QueryConvertor.parseFilter(filterType, OrgType.class, getPrismContext()); - ObjectQuery query = ObjectQuery.createObjectQuery(filter); + " "; + QueryType queryJaxb = toQueryType(queryXml); + displayQueryType(queryJaxb); + ObjectQuery query = toObjectQuery(OrgType.class, queryJaxb); + displayQuery(query); ObjectQuery expectedQuery = QueryBuilder.queryFor(OrgType.class, getPrismContext()).isChildOf("333").build(); - // primitive way of comparing queries - assertEquals("Parsed query is wrong", expectedQuery.toString(), query.toString()); + assertEquals("Parsed query is wrong", expectedQuery.toString(), query.toString()); // primitive way of comparing queries - // now reserialize the parsed query and compare with XML - String expected = "\n" + - " \n" + - " 333\n" + - " \n" + - " SUBTREE\n" + - " "; + // now reserialize the parsed query and compare with XML - the XML contains explicit scope=SUBTREE (as this is set when parsing original queryXml) + checkQueryRoundtripFile(OrgType.class, query, TEST_NAME); + } - checkQuery(query, expected); + @Test + public void test500InOid() throws Exception { + final String TEST_NAME = "test500InOid"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .id("oid1", "oid2", "oid3") + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); } + @Test + public void test510InOidContainer() throws Exception { + final String TEST_NAME = "test510InOidContainer"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .id(1, 2, 3) + .and().ownerId("oid4") + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - private void assertXml(QueryType queryType, String expected) throws SchemaException { - MapXNode mapXNode = queryType.getFilter().getFilterClauseXNode(); - String realWrapped = getPrismContext().serializeXNodeToString(new RootXNode(new QName("query"), mapXNode), PrismContext.LANG_XML); + @Test + public void test590Logicals() throws Exception { + final String TEST_NAME = "test590Logicals"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) + .block() + .all() + .or().none() + .or().undefined() + .endBlock() + .and().none() + .and() + .not() + .block() + .all() + .and().undefined() + .endBlock() + .build(); + checkQueryRoundtripFile(UserType.class, q, TEST_NAME); + } - // primitive but effective method - int start = realWrapped.indexOf('>')+1; - int end = realWrapped.lastIndexOf('<'); - String real = realWrapped.substring(start, end); + @Test + public void test600Type() throws Exception { + final String TEST_NAME = "test600Type"; + displayTestTitle(TEST_NAME); + ObjectQuery q = QueryBuilder.queryFor(ObjectType.class, getPrismContext()) + .type(UserType.class) + .item(UserType.F_NAME).eqPoly("somename", "somename") + .build(); + checkQueryRoundtripFile(ObjectType.class, q, TEST_NAME); + } - String expNorm = StringUtils.normalizeSpace(expected); - String realNorm = StringUtils.normalizeSpace(real); - if (!expNorm.equals(realNorm)) { - String m = "Serialized 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 test700Exists() throws Exception { + final String TEST_NAME = "test700Exists"; + displayTestTitle(TEST_NAME); + PrismReferenceValue ownerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER).asReferenceValue(); + ObjectQuery q = QueryBuilder.queryFor(AccessCertificationCaseType.class, getPrismContext()) + .exists(T_PARENT) + .block() + .id(123456L) + .or().item(F_OWNER_REF).ref(ownerRef) + .endBlock() + .and().item(AccessCertificationCaseType.F_DECISION, AccessCertificationDecisionType.F_STAGE_NUMBER).eq(3) + .build(); + checkQueryRoundtripFile(AccessCertificationCaseType.class, q, TEST_NAME); } + } diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/test/XPathTest.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/test/XPathTest.java index 2504001c6d4..f25726d16da 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/test/XPathTest.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/test/XPathTest.java @@ -390,6 +390,23 @@ public void testXPathSerializationToDom() { assertTrue("Paths are not equivalent", xpath1.equivalent(xpath2)); } + @Test + public void parseSpecial() { + final String D = "declare namespace x='http://xyz.com/'; "; + AssertJUnit.assertEquals("..", TrivialXPathParser.parse("..").getPureXPathString()); + AssertJUnit.assertEquals("..", TrivialXPathParser.parse(D+"..").getPureXPathString()); + AssertJUnit.assertEquals("a/../b", TrivialXPathParser.parse("a/../b").getPureXPathString()); + AssertJUnit.assertEquals("a/../b", TrivialXPathParser.parse(D+"a/../b").getPureXPathString()); + AssertJUnit.assertEquals("@", TrivialXPathParser.parse("@").getPureXPathString()); + AssertJUnit.assertEquals("@", TrivialXPathParser.parse(D+"@").getPureXPathString()); + AssertJUnit.assertEquals("a/@/b", TrivialXPathParser.parse("a/@/b").getPureXPathString()); + AssertJUnit.assertEquals("a/@/b", TrivialXPathParser.parse(D+"a/@/b").getPureXPathString()); + AssertJUnit.assertEquals("#", TrivialXPathParser.parse("#").getPureXPathString()); + AssertJUnit.assertEquals("#", TrivialXPathParser.parse(D+"#").getPureXPathString()); + AssertJUnit.assertEquals("a/#/b", TrivialXPathParser.parse("a/#/b").getPureXPathString()); + AssertJUnit.assertEquals("a/#/b", TrivialXPathParser.parse(D+"a/#/b").getPureXPathString()); + } + //not actual anymore..we have something like "wildcard" in xpath..there don't need to be prefix specified.we will try to match the local names @Test(enabled=false) public void testUndefinedPrefix() throws ParserConfigurationException, SAXException, IOException { diff --git a/infra/schema/src/test/resources/queryconvertor/filter-account.xml b/infra/schema/src/test/resources/queryconvertor/filter-account.xml index 7683fcd99e3..27769b9f175 100644 --- a/infra/schema/src/test/resources/queryconvertor/filter-account.xml +++ b/infra/schema/src/test/resources/queryconvertor/filter-account.xml @@ -23,14 +23,14 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + insensitive c:failedOperationType add - insensitive + norm c:name someName - norm diff --git a/infra/schema/src/test/resources/queryconvertor/test100All.xml b/infra/schema/src/test/resources/queryconvertor/test100All.xml new file mode 100644 index 00000000000..9afe2237d9a --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test100All.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test110None.xml b/infra/schema/src/test/resources/queryconvertor/test110None.xml new file mode 100644 index 00000000000..3d517890aa6 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test110None.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test120Undefined.xml b/infra/schema/src/test/resources/queryconvertor/test120Undefined.xml new file mode 100644 index 00000000000..8aa2d35922e --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test120Undefined.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test200Equal.xml b/infra/schema/src/test/resources/queryconvertor/test200Equal.xml new file mode 100644 index 00000000000..af154eaa559 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test200Equal.xml @@ -0,0 +1,26 @@ + + + + + + + polyStringOrig + c:name + some-name + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test210EqualMultiple.xml b/infra/schema/src/test/resources/queryconvertor/test210EqualMultiple.xml new file mode 100644 index 00000000000..640931bc0e2 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test210EqualMultiple.xml @@ -0,0 +1,26 @@ + + + + + + + c:employeeType + STD + TEMP + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test220EqualRightHandItem.xml b/infra/schema/src/test/resources/queryconvertor/test220EqualRightHandItem.xml new file mode 100644 index 00000000000..75c224da2cc --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test220EqualRightHandItem.xml @@ -0,0 +1,25 @@ + + + + + + + c:employeeNumber + c:costCenter + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test300Greater.xml b/infra/schema/src/test/resources/queryconvertor/test300Greater.xml new file mode 100644 index 00000000000..55866880985 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test300Greater.xml @@ -0,0 +1,25 @@ + + + + + + + c:costCenter + 100000 + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test310AllComparisons.xml b/infra/schema/src/test/resources/queryconvertor/test310AllComparisons.xml new file mode 100644 index 00000000000..6f5c071d606 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test310AllComparisons.xml @@ -0,0 +1,43 @@ + + + + + + + + + c:costCenter + 100000 + + + c:costCenter + 999999 + + + + + c:costCenter + X100 + + + c:costCenter + X999 + + + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test350Substring.xml b/infra/schema/src/test/resources/queryconvertor/test350Substring.xml new file mode 100644 index 00000000000..01222881c54 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test350Substring.xml @@ -0,0 +1,43 @@ + + + + + + + + c:employeeType + A + + + c:employeeType + B + true + + + c:employeeType + C + true + + + polyStringOrig + c:name + john + true + + + + \ No newline at end of file diff --git a/infra/schema/src/test/resources/queryconvertor/test360Ref.xml b/infra/schema/src/test/resources/queryconvertor/test360Ref.xml new file mode 100644 index 00000000000..47c29112441 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test360Ref.xml @@ -0,0 +1,44 @@ + + + + + + + c:resourceRef + + + + c:resourceRef + + + + c:resourceRef + + oid3 + + + + c:resourceRef + + oid4 + c:ResourceType + + + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test365RefTwoWay.xml b/infra/schema/src/test/resources/queryconvertor/test365RefTwoWay.xml new file mode 100644 index 00000000000..6947676fc07 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test365RefTwoWay.xml @@ -0,0 +1,38 @@ + + + + + + + + c:resourceRef + + + + c:resourceRef + + + + c:resourceRef + + + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test400OrgFilterRoot.xml b/infra/schema/src/test/resources/queryconvertor/test400OrgFilterRoot.xml new file mode 100644 index 00000000000..edb54e11978 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test400OrgFilterRoot.xml @@ -0,0 +1,24 @@ + + + + + + + true + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test410OrgFilterSubtree.xml b/infra/schema/src/test/resources/queryconvertor/test410OrgFilterSubtree.xml new file mode 100644 index 00000000000..8e9dfe13d28 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test410OrgFilterSubtree.xml @@ -0,0 +1,11 @@ + + + + + + 111 + + SUBTREE + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test420OrgFilterDirect.xml b/infra/schema/src/test/resources/queryconvertor/test420OrgFilterDirect.xml new file mode 100644 index 00000000000..9b70a5b7de5 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test420OrgFilterDirect.xml @@ -0,0 +1,27 @@ + + + + + + + + 222 + + ONE_LEVEL + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test430OrgFilterDefaultScope.xml b/infra/schema/src/test/resources/queryconvertor/test430OrgFilterDefaultScope.xml new file mode 100644 index 00000000000..fd6d012bb8a --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test430OrgFilterDefaultScope.xml @@ -0,0 +1,27 @@ + + + + + + + + 333 + + SUBTREE + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test500InOid.xml b/infra/schema/src/test/resources/queryconvertor/test500InOid.xml new file mode 100644 index 00000000000..1fb18e3077d --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test500InOid.xml @@ -0,0 +1,26 @@ + + + + + + + oid1 + oid2 + oid3 + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test510InOidContainer.xml b/infra/schema/src/test/resources/queryconvertor/test510InOidContainer.xml new file mode 100644 index 00000000000..80396209e0f --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test510InOidContainer.xml @@ -0,0 +1,32 @@ + + + + + + + + 1 + 2 + 3 + + + oid4 + true + + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test590Logicals.xml b/infra/schema/src/test/resources/queryconvertor/test590Logicals.xml new file mode 100644 index 00000000000..7b121ef1be2 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test590Logicals.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test600Type.xml b/infra/schema/src/test/resources/queryconvertor/test600Type.xml new file mode 100644 index 00000000000..cd98eda2518 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test600Type.xml @@ -0,0 +1,30 @@ + + + + + + + c:UserType + + + c:name + somename + + + + + diff --git a/infra/schema/src/test/resources/queryconvertor/test700Exists.xml b/infra/schema/src/test/resources/queryconvertor/test700Exists.xml new file mode 100644 index 00000000000..1714108be92 --- /dev/null +++ b/infra/schema/src/test/resources/queryconvertor/test700Exists.xml @@ -0,0 +1,44 @@ + + + + + + + + .. + + + + 123456 + + + c:ownerRef + + + + + + + c:decision/c:stageNumber + 3 + + + + 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 c85149d7899..9f7ba7be4ee 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 @@ -178,15 +178,10 @@ public List searchDecisions(ObjectQuery query, Stri 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_CURRENT_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) + .and().item(T_PARENT, F_STATE).eq(IN_REVIEW_STAGE) .buildFilter(); } 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 648abfde642..8c969f10f5b 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 @@ -408,14 +408,9 @@ public void test330CurrentUnansweredCases() throws Exception { OperationResult result = new OperationResult("test330CurrentUnansweredCases"); // 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); ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) .item(F_CURRENT_STAGE_NUMBER).eq().item(T_PARENT, AccessCertificationCampaignType.F_STAGE_NUMBER) - .and().item(statePath, stateDef).eq(IN_REVIEW_STAGE) + .and().item(T_PARENT, F_STATE).eq(IN_REVIEW_STAGE) .and().exists(F_DECISION).block() .item(F_STAGE_NUMBER).eq().item(T_PARENT, F_CURRENT_STAGE_NUMBER) .and().block() 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 1a764e817fb..1225d61f581 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 @@ -2814,13 +2814,11 @@ public void test740QueryCertCasesByCampaignOwner() throws Exception { Session session = open(); try { PrismReferenceValue ownerRef = ObjectTypeUtil.createObjectRef("1234567890", ObjectTypes.USER).asReferenceValue(); - PrismObjectDefinition campaignDef = - prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(AccessCertificationCampaignType.class); ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) .exists(T_PARENT) .block() .id(123456L) - .or().item(campaignDef, F_OWNER_REF).ref(ownerRef) + .or().item(F_OWNER_REF).ref(ownerRef) .endBlock() .build(); @@ -2932,15 +2930,10 @@ public void test747QueryCertCaseReviewerAndEnabledByRequestedDesc() throws Excep Session session = open(); try { 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_CURRENT_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) + .and().item(T_PARENT, F_STATE).eq(IN_REVIEW_STAGE) .desc(F_CURRENT_REVIEW_REQUESTED_TIMESTAMP) .build(); String real = getInterpretedQuery2(session, AccessCertificationCaseType.class, query, false); 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 index 5fab50e5165..8e9f3c79521 100644 --- 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 @@ -52,4 +52,25 @@ protected void copyTo(ObjectPagingAfterOid clone) { super.copyTo(clone); clone.oidGreaterThan = this.oidGreaterThan; } + + public boolean equals(Object o, boolean exact) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o, exact)) + return false; + + ObjectPagingAfterOid that = (ObjectPagingAfterOid) o; + + return oidGreaterThan != null ? oidGreaterThan.equals(that.oidGreaterThan) : that.oidGreaterThan == null; + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (oidGreaterThan != null ? oidGreaterThan.hashCode() : 0); + return result; + } } 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 2ee593c12fb..117e22311ee 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 @@ -44,7 +44,7 @@ public Condition interpretInternal() throws QueryException { String propertyValuePath = getHqlDataInstance().getHqlPath(); - if (filter.getRightSidePath() != null) { + if (filter.getRightHandSidePath() != null) { return createPropertyVsPropertyCondition(propertyValuePath); } else { Object value = RAnyConverter.getAggregatedRepoObject(getValue(filter)); 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 fbf7fc5baac..35d9cf7ce18 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 @@ -65,7 +65,7 @@ public Condition interpretInternal() throws QueryException { } String propertyValuePath = getHqlDataInstance().getHqlPath(); - if (filter.getRightSidePath() != null) { + if (filter.getRightHandSidePath() != null) { return createPropertyVsPropertyCondition(propertyValuePath); } else { Object value = getValueFromFilter(filter); @@ -75,8 +75,8 @@ public Condition interpretInternal() throws QueryException { } protected Condition createPropertyVsPropertyCondition(String leftPropertyValuePath) throws QueryException { - HqlDataInstance rightItem = getItemPathResolver().resolveItemPath(filter.getRightSidePath(), - filter.getRightSideDefinition(), getBaseHqlEntityForChildren(), true); + HqlDataInstance rightItem = getItemPathResolver().resolveItemPath(filter.getRightHandSidePath(), + filter.getRightHandSideDefinition(), getBaseHqlEntityForChildren(), true); String rightHqlPath = rightItem.getHqlPath(); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); 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 6b6cab195bd..9ee673fe979 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 @@ -511,7 +511,7 @@ private static QueryType createUserQuery2(String username) throws JAXBException 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); + fc.getValue().add(username); ObjectFactory factory = new ObjectFactory(); JAXBElement equal = factory.createEqual(fc); From d25afcb90a492f2f013265cd8ef904a93e5beb6f Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Wed, 4 May 2016 10:48:06 +0200 Subject: [PATCH 06/12] Fixing association and prims multivalue stylesheets --- .../component/AssociationValueChoicePanel.html | 18 ++++++++---------- .../src/main/webapp/less/midpoint-theme.less | 4 ++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoicePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoicePanel.html index a74c7307b31..3fe4bfca862 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoicePanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/AssociationValueChoicePanel.html @@ -1,5 +1,5 @@ + + + + + + Embedded Test OpenDJ - Dumber version + + + + + + 10389 + localhost + dc=example,dc=com + cn=directory manager + secret + auto + entryUUID + ds-pwp-account-disabled + isMemberOf + createTimestamp + never + + + + 120000 + 1 + 10 + 10 + 150000 + + + 100 + + + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + false + false + false + + + + + http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff + + + + + + + account + default + Default Account + true + ri:inetOrgPerson + + ri:isMemberOf + explicit + + + ri:secretary + mr:xml + explicit + + + ri:group + LDAP Group Membership + entitlement + ldapGroup + objectToSubject + ri:uniqueMember + ri:dn + true + + + + + http://prism.evolveum.com/xml/ns/public/matching-rule-3#distinguishedName + attributes/ri:dn + + uid=cAlyPSo, ou=PeoPle, DC=example,dc=COM + + + + + + ri:uid + + + sequentialSearch + + + + + + entitlement + ldapGroup + LDAP Group + ri:groupOfUniqueNames + + ri:organizationalUnit + + + attributes/dn + ou=groups,dc=example,dc=com + + + + + ri:entryUUID + mr:stringIgnoreCase + + + ri:dn + mr:distinguishedName + + + ri:uniqueMember + mr:distinguishedName + minimal + + + + + + entitlement + specialGroup + Special LDAP Group + ri:groupOfUniqueNames + + ri:organizationalUnit + + + attributes/dn + ou=specialgroups,dc=example,dc=com + + + + + ri:entryUUID + mr:stringIgnoreCase + + + ri:dn + mr:distinguishedName + + + ri:uniqueMember + mr:distinguishedName + minimal + + + + + + generic + ou-people + Organizational Unit + ri:organizationalUnit + + ri:organizationalUnit + + + attributes/dn + ou=People,dc=example,dc=com + + + + + ri:entryUUID + mr:stringIgnoreCase + + + ri:dn + mr:distinguishedName + + + + + + + true + + + + + + + ri:ds-pwp-account-disabled + + true + + + + ri:pager + + 1 + + + + + + + + + + + diff --git a/provisioning/provisioning-impl/testng-integration.xml b/provisioning/provisioning-impl/testng-integration.xml index f50e3943607..eb5f845f62c 100644 --- a/provisioning/provisioning-impl/testng-integration.xml +++ b/provisioning/provisioning-impl/testng-integration.xml @@ -28,8 +28,9 @@ - - + + + diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java index bb57e4b0341..6f746750bc9 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java @@ -619,7 +619,7 @@ protected void assertShadowCommon(PrismObject shadow, String oid, St RefinedResourceSchema rSchema = RefinedResourceSchema.getRefinedSchema(resourceType); ObjectClassComplexTypeDefinition ocDef = rSchema.findObjectClassDefinition(objectClass); if (ocDef.getSecondaryIdentifiers().isEmpty()) { - ResourceAttributeDefinition idDef = ocDef.getIdentifiers().iterator().next(); + ResourceAttributeDefinition idDef = ocDef.getPrimaryIdentifiers().iterator().next(); PrismProperty idProp = attributesContainer.findProperty(idDef.getName()); assertNotNull("No primary identifier ("+idDef.getName()+") attribute in shadow for "+username, idProp); if (nameMatchingRule == null) { @@ -941,7 +941,7 @@ protected PrismObject findShadowByName(QName objectClass, String nam protected ObjectQuery createAccountShadowQuery(String identifier, PrismObject resource) throws SchemaException { RefinedResourceSchema rSchema = RefinedResourceSchema.getRefinedSchema(resource); RefinedObjectClassDefinition rAccount = rSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); - Collection identifierDefs = rAccount.getIdentifiers(); + Collection identifierDefs = rAccount.getPrimaryIdentifiers(); assert identifierDefs.size() == 1 : "Unexpected identifier set in "+resource+" refined schema: "+identifierDefs; ResourceAttributeDefinition identifierDef = identifierDefs.iterator().next(); //TODO: set matching rule instead of null diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java index b2a863d15d8..fed6bcbf4e9 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java @@ -295,8 +295,8 @@ public void assertRefinedSchemaSanity(RefinedResourceSchema refinedSchema) { RefinedObjectClassDefinition accountDef = refinedSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); assertNotNull("Account definition is missing", accountDef); - assertNotNull("Null identifiers in account", accountDef.getIdentifiers()); - assertFalse("Empty identifiers in account", accountDef.getIdentifiers().isEmpty()); + assertNotNull("Null identifiers in account", accountDef.getPrimaryIdentifiers()); + assertFalse("Empty identifiers in account", accountDef.getPrimaryIdentifiers().isEmpty()); assertNotNull("Null secondary identifiers in account", accountDef.getSecondaryIdentifiers()); assertFalse("Empty secondary identifiers in account", accountDef.getSecondaryIdentifiers().isEmpty()); assertNotNull("No naming attribute in account", accountDef.getNamingAttribute()); @@ -309,7 +309,7 @@ public void assertRefinedSchemaSanity(RefinedResourceSchema refinedSchema) { assertFalse("UID has create", uidDef.canAdd()); assertFalse("UID has update",uidDef.canModify()); assertTrue("No UID read",uidDef.canRead()); - assertTrue("UID definition not in identifiers", accountDef.getIdentifiers().contains(uidDef)); + assertTrue("UID definition not in identifiers", accountDef.getPrimaryIdentifiers().contains(uidDef)); RefinedAttributeDefinition nameDef = accountDef.findAttributeDefinition(SchemaTestConstants.ICFS_NAME); assertEquals(1, nameDef.getMaxOccurs()); 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 6a06e70c883..059b4c9f56d 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Evolveum + * Copyright (c) 2010-2016 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -308,7 +308,7 @@ public static void assertProvisioningShadow(PrismObject account, Res ObjectClassComplexTypeDefinition objectClassDef = rAttrsDef.getComplexTypeDefinition(); assertNotNull("No object class definition in attributes definition", objectClassDef); assertEquals("Wrong object class in attributes definition", objectClass, objectClassDef.getTypeName()); - ResourceAttributeDefinition primaryIdDef = objectClassDef.getIdentifiers().iterator().next(); + ResourceAttributeDefinition primaryIdDef = objectClassDef.getPrimaryIdentifiers().iterator().next(); ResourceAttribute primaryIdAttr = rAttributesContainer.findAttribute(primaryIdDef.getName()); assertNotNull("No primary ID "+primaryIdDef.getName()+" in "+account, primaryIdAttr); assertAttributeDefinition(primaryIdAttr, DOMUtil.XSD_STRING, 0, 1, true, false, false, expetcedAttributeDefinitionClass); @@ -604,7 +604,7 @@ public static void checkShadow(ShadowType shadowType, ResourceType resourceType, String icfUid = ShadowUtil.getSingleStringAttributeValue(shadowType, SchemaTestConstants.ICFS_UID); if (icfUid == null) { - Collection identifierDefs = objectClassDef.getIdentifiers(); + Collection identifierDefs = objectClassDef.getPrimaryIdentifiers(); assertFalse("No identifiers for "+objectClassDef, identifierDefs == null || identifierDefs.isEmpty()); for (ResourceAttributeDefinition idDef: identifierDefs) { String id = ShadowUtil.getSingleStringAttributeValue(shadowType, idDef.getName()); @@ -673,7 +673,7 @@ private static void checkShadowUniqueness(ShadowType resourceShadow, ObjectClass private static ObjectQuery createShadowQuery(ShadowType resourceShadow, ObjectClassComplexTypeDefinition objectClassDef, MatchingRule uidMatchingRule, PrismContext prismContext) throws SchemaException { PrismContainer attributesContainer = resourceShadow.asPrismObject().findContainer(ShadowType.F_ATTRIBUTES); - QName identifierName = objectClassDef.getIdentifiers().iterator().next().getName(); + QName identifierName = objectClassDef.getPrimaryIdentifiers().iterator().next().getName(); PrismProperty identifier = attributesContainer.findProperty(identifierName); if (identifier == null) { throw new SchemaException("No identifier in "+resourceShadow); @@ -778,7 +778,7 @@ public static void assertIcfResourceSchemaSanity(ResourceSchema resourceSchema, assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isEmpty()); assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isIgnored()); - Collection identifiers = accountDefinition.getIdentifiers(); + Collection identifiers = accountDefinition.getPrimaryIdentifiers(); assertNotNull("Null identifiers for " + objectClassQname, identifiers); assertFalse("Empty identifiers for " + objectClassQname, identifiers.isEmpty()); @@ -801,8 +801,8 @@ public static void assertIcfResourceSchemaSanity(ResourceSchema resourceSchema, assertEquals("Wrong displayName for attribute "+SchemaTestConstants.ICFS_NAME, "ConnId Name", nameAttributeDefinition.getDisplayName()); assertEquals("Wrong displayOrder for attribute "+SchemaTestConstants.ICFS_NAME, (Integer)110, nameAttributeDefinition.getDisplayOrder()); - assertNotNull("Null identifiers in account", accountDef.getIdentifiers()); - assertFalse("Empty identifiers in account", accountDef.getIdentifiers().isEmpty()); + assertNotNull("Null identifiers in account", accountDef.getPrimaryIdentifiers()); + assertFalse("Empty identifiers in account", accountDef.getPrimaryIdentifiers().isEmpty()); assertNotNull("Null secondary identifiers in account", accountDef.getSecondaryIdentifiers()); assertFalse("Empty secondary identifiers in account", accountDef.getSecondaryIdentifiers().isEmpty()); assertNotNull("No naming attribute in account", accountDef.getNamingAttribute()); @@ -816,7 +816,7 @@ public static void assertIcfResourceSchemaSanity(ResourceSchema resourceSchema, assertFalse("UID has create", uidDef.canAdd()); assertFalse("UID has update",uidDef.canModify()); assertTrue("No UID read",uidDef.canRead()); - assertTrue("UID definition not in identifiers", accountDef.getIdentifiers().contains(uidDef)); + assertTrue("UID definition not in identifiers", accountDef.getPrimaryIdentifiers().contains(uidDef)); assertEquals("Wrong refined displayName for attribute "+SchemaTestConstants.ICFS_UID, "ConnId UID", uidDef.getDisplayName()); assertEquals("Wrong refined displayOrder for attribute "+SchemaTestConstants.ICFS_UID, (Integer)100, uidDef.getDisplayOrder()); @@ -899,7 +899,7 @@ public static void assertNoGroupMembers(DummyGroup group) { assertTrue("Group "+group.getName()+" has members while not expecting it, members: "+members, members == null || members.isEmpty()); } - public static void assertAssociation(PrismObject shadow, QName associationName, String entitlementOid) { + public static ShadowAssociationType assertAssociation(PrismObject shadow, QName associationName, String entitlementOid) { ShadowType accountType = shadow.asObjectable(); List associations = accountType.getAssociation(); assertNotNull("Null associations in "+shadow, associations); @@ -907,10 +907,11 @@ public static void assertAssociation(PrismObject shadow, QName assoc for (ShadowAssociationType association: associations) { if (associationName.equals(association.getName()) && entitlementOid.equals(association.getShadowRef().getOid())) { - return; + return association; } } AssertJUnit.fail("No association for entitlement "+entitlementOid+" in "+shadow); + return null; // notreached } public static void assertNoAssociation(PrismObject shadow, QName associationName, String entitlementOid) { diff --git a/samples/evolveum/resource-openldap.xml b/samples/evolveum/resource-openldap.xml index 124734c706a..e235ff947bd 100644 --- a/samples/evolveum/resource-openldap.xml +++ b/samples/evolveum/resource-openldap.xml @@ -391,28 +391,17 @@ - true + ri:inetOrgPerson + account + default + UserType - - Correlation expression is a search query. - Following search queury will look for users that have "name" - equal to the "uid" attribute of the account. Simply speaking, - it will look for match in usernames in the IDM and the resource. - The correlation rule always looks for users, so it will not match - any other object type. - name - - declare namespace - ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"; - $account/attributes/ri:uid - + $account/attributes/uid @@ -430,7 +419,45 @@ + + unlinked + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#link + + + + + + + true + ri:groupOfNames + entitlement + ldapGroup + OrgType + + + + name + + $account/attributes/cn + + + + + + linked + true + + + deleted + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink + + + unlinked true @@ -439,16 +466,48 @@ + + + + true + ri:posixGroup + entitlement + posixGroup + OrgType + + + + name + + $account/attributes/cn + + + + + + + linked + true + + + deleted + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink + + + - unmatched + unlinked true - http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus + http://midpoint.evolveum.com/xml/ns/public/model/action-3#link - + + diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/Abstract389DsDnTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/Abstract389DsDnTest.java index ce0707f278d..2227a0b9216 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/Abstract389DsDnTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/Abstract389DsDnTest.java @@ -66,7 +66,7 @@ public void test025SchemaDn() throws Exception { assertTrue("dn modify", dnDef.canModify()); assertTrue("dn add", dnDef.canAdd()); - assertTrue("Dn is not an identifier", accountObjectClassDefinition.getIdentifiers().contains(dnDef)); + assertTrue("Dn is not an identifier", accountObjectClassDefinition.getPrimaryIdentifiers().contains(dnDef)); assertTrue("Secodary identifiers are not empty: "+accountObjectClassDefinition.getSecondaryIdentifiers(), accountObjectClassDefinition.getSecondaryIdentifiers().isEmpty()); } diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java index 75496983f37..c0c95749766 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java @@ -696,7 +696,7 @@ public void test200AssignAccountBarbossa() throws Exception { PrismObject shadow = getShadowModel(shadowOid); display("Shadow (model)", shadow); accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getIdentifiers(shadow); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); assertNotNull("No identifier in "+shadow, accountBarbossaIcfUid); diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractEDirTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractEDirTest.java index 4ce4b9fc2ff..e620c571aea 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractEDirTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractEDirTest.java @@ -466,7 +466,7 @@ public void test200AssignAccountBarbossa() throws Exception { PrismObject shadow = getShadowModel(shadowOid); display("Shadow (model)", shadow); accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getIdentifiers(shadow); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); assertNotNull("No identifier in "+shadow, accountBarbossaIcfUid); diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java index 14c91d2c85d..51fa05894cc 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java @@ -669,7 +669,7 @@ public void test200AssignAccountToBarbossa() throws Exception { PrismObject shadow = getShadowModel(shadowOid); display("Shadow (model)", shadow); accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getIdentifiers(shadow); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); accountBarbossaEntryId = (String) identifiers.iterator().next().getRealValue(); assertNotNull("No identifier in "+shadow, accountBarbossaEntryId); diff --git a/testing/consistency-mechanism/src/test/java/com/evolveum/midpoint/testing/consistency/ConsistencyTest.java b/testing/consistency-mechanism/src/test/java/com/evolveum/midpoint/testing/consistency/ConsistencyTest.java index a3cb1c18fa0..c01c3f55c8e 100644 --- a/testing/consistency-mechanism/src/test/java/com/evolveum/midpoint/testing/consistency/ConsistencyTest.java +++ b/testing/consistency-mechanism/src/test/java/com/evolveum/midpoint/testing/consistency/ConsistencyTest.java @@ -672,7 +672,7 @@ public void test122AddAccountAlreadyExistUnlinked() throws Exception { assertEquals("shadow secondary identifier not equal with the account dn. ", dn, attributes .findAttribute(getOpenDjSecondaryIdentifierQName()).getRealValue(String.class)); - String identifier = attributes.getIdentifier().getRealValue(String.class); + String identifier = attributes.getPrimaryIdentifier().getRealValue(String.class); openDJController.searchAndAssertByEntryUuid(identifier); @@ -1942,7 +1942,7 @@ public void test800Reconciliation() throws Exception { assertAttribute(eAccount, resourceTypeOpenDjrepo, "employeeNumber", "emp4321"); ResourceAttributeContainer attributeContainer = ShadowUtil .getAttributesContainer(eAccount); - Collection> identifiers = attributeContainer.getIdentifiers(); + Collection> identifiers = attributeContainer.getPrimaryIdentifiers(); assertNotNull(identifiers); assertFalse(identifiers.isEmpty()); assertEquals(1, identifiers.size()); @@ -2012,7 +2012,7 @@ public void test801TestReconciliationRename() throws Exception{ assertAttribute(eAccount, resourceTypeOpenDjrepo, "employeeNumber", "emp4321"); ResourceAttributeContainer attributeContainer = ShadowUtil .getAttributesContainer(eAccount); - Collection> identifiers = attributeContainer.getIdentifiers(); + Collection> identifiers = attributeContainer.getPrimaryIdentifiers(); assertNotNull(identifiers); assertFalse(identifiers.isEmpty()); assertEquals(1, identifiers.size()); @@ -2093,7 +2093,7 @@ private void checkOpenDjSchema(ResourceType resource, String source) throws Sche ResourceSchema schema = RefinedResourceSchema.getResourceSchema(resource, prismContext); ObjectClassComplexTypeDefinition accountDefinition = schema.findObjectClassDefinition(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS); assertNotNull("Schema does not define any account (resource from " + source + ")", accountDefinition); - Collection identifiers = accountDefinition.getIdentifiers(); + Collection identifiers = accountDefinition.getPrimaryIdentifiers(); assertFalse("No account identifiers (resource from " + source + ")", identifiers == null || identifiers.isEmpty()); // TODO: check for naming attributes and display names, etc diff --git a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java b/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java index 58a65198289..a1a16b15345 100644 --- a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java +++ b/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java @@ -590,7 +590,7 @@ private void checkOpenDjSchema(ResourceType resource, String source) throws Sche ResourceSchema schema = RefinedResourceSchema.getResourceSchema(resource, prismContext); ObjectClassComplexTypeDefinition accountDefinition = schema.findObjectClassDefinition(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS); assertNotNull("Schema does not define any account (resource from " + source + ")", accountDefinition); - Collection identifiers = accountDefinition.getIdentifiers(); + Collection identifiers = accountDefinition.getPrimaryIdentifiers(); assertFalse("No account identifiers (resource from " + source + ")", identifiers == null || identifiers.isEmpty()); // TODO: check for naming attributes and display names, etc @@ -4154,7 +4154,7 @@ public static String getNormalizedAttributeValue(ShadowType repoShadow, RefinedO String value = getAttributeValue(repoShadow, name); - RefinedAttributeDefinition idDef = objClassDef.getIdentifiers().iterator().next(); + RefinedAttributeDefinition idDef = objClassDef.getPrimaryIdentifiers().iterator().next(); if (idDef.getMatchingRuleQName() != null && idDef.getMatchingRuleQName().equals(StringIgnoreCaseMatchingRule.NAME)){ return value.toLowerCase(); } diff --git a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanityLegacy.java b/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanityLegacy.java index 078521481cc..e830c7ba2dc 100644 --- a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanityLegacy.java +++ b/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanityLegacy.java @@ -578,7 +578,7 @@ private void checkOpenDjSchema(ResourceType resource, String source) throws Sche ResourceSchema schema = RefinedResourceSchema.getResourceSchema(resource, prismContext); ObjectClassComplexTypeDefinition accountDefinition = schema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT); assertNotNull("Schema does not define any account (resource from " + source + ")", accountDefinition); - Collection identifiers = accountDefinition.getIdentifiers(); + Collection identifiers = accountDefinition.getPrimaryIdentifiers(); assertFalse("No account identifiers (resource from " + source + ")", identifiers == null || identifiers.isEmpty()); // TODO: check for naming attributes and display names, etc From c139201148396057ca96590bd67354e528d0989d Mon Sep 17 00:00:00 2001 From: Viliam Repan Date: Wed, 4 May 2016 15:47:37 +0200 Subject: [PATCH 12/12] typo fix for search --- .../com/evolveum/midpoint/web/component/search/SearchPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchPanel.java index ce3777cd2e2..27ead105e43 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/search/SearchPanel.java @@ -327,7 +327,7 @@ public void onClick(AjaxRequestTarget target) { name.setRenderBodyOnly(true); propLink.add(name); - propLink.add(new VisibleEnableBehaviour() { + item.add(new VisibleEnableBehaviour() { @Override public boolean isVisible() {