Fix OPENDJ-376: Add isInScopeOf, localName, and rename methods to DN class
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.ldap; |
| | |
| | | parent = ROOT_DN; |
| | | } |
| | | |
| | | return new DN(rdn, parent, dnString); |
| | | return new DN(parent, rdn, dnString); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | private final RDN rdn; |
| | | |
| | | private final DN parent; |
| | | private DN parent; |
| | | |
| | | private final int size; |
| | | |
| | |
| | | |
| | | |
| | | // Private constructor. |
| | | private DN(final RDN rdn, final DN parent, final String stringValue) |
| | | private DN(final DN parent, final RDN rdn, final String stringValue) |
| | | { |
| | | this.rdn = rdn; |
| | | this(parent, rdn, stringValue, parent != null ? parent.size + 1 : 0); |
| | | } |
| | | |
| | | |
| | | |
| | | // Private constructor. |
| | | private DN(final DN parent, final RDN rdn, final String stringValue, |
| | | final int size) |
| | | { |
| | | this.parent = parent; |
| | | this.rdn = rdn; |
| | | this.stringValue = stringValue; |
| | | this.size = parent != null ? parent.size + 1 : 0; |
| | | this.size = size; |
| | | } |
| | | |
| | | |
| | |
| | | DN newDN = this; |
| | | for (i = 0; i < rdns.length; i++) |
| | | { |
| | | newDN = new DN(rdns[i], newDN, null); |
| | | newDN = new DN(newDN, rdns[i], null); |
| | | } |
| | | return newDN; |
| | | } |
| | |
| | | public DN child(final RDN rdn) throws NullPointerException |
| | | { |
| | | Validator.ensureNotNull(rdn); |
| | | return new DN(rdn, this, null); |
| | | return new DN(this, rdn, null); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if this DN matches the provided base DN and search |
| | | * scope. |
| | | * |
| | | * @param dn |
| | | * The base DN. |
| | | * @param scope |
| | | * The search scope. |
| | | * @return {@code true} if this DN matches the provided base DN and search |
| | | * scope, otherwise {@code false}. |
| | | * @throws NullPointerException |
| | | * If {@code dn} or {@code scope} was {@code null}. |
| | | */ |
| | | public boolean isInScopeOf(DN dn, SearchScope scope) |
| | | { |
| | | if (scope == SearchScope.BASE_OBJECT) |
| | | { |
| | | // The base DN must equal this DN. |
| | | return equals(dn); |
| | | } |
| | | else if (scope == SearchScope.SINGLE_LEVEL) |
| | | { |
| | | // The parent DN must equal the base DN. |
| | | return isChildOf(dn); |
| | | } |
| | | else if (scope == SearchScope.SUBORDINATES) |
| | | { |
| | | // This DN must be a descendant of the provided base DN, but |
| | | // not equal to it. |
| | | return isSubordinateOrEqualTo(dn) && !equals(dn); |
| | | } |
| | | else if (scope == SearchScope.WHOLE_SUBTREE) |
| | | { |
| | | // This DN must be a descendant of the provided base DN. |
| | | return isSubordinateOrEqualTo(dn); |
| | | } |
| | | else |
| | | { |
| | | // This is a scope that we don't recognize. |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if this DN matches the provided base DN and search |
| | | * scope. |
| | | * |
| | | * @param dn |
| | | * The base DN. |
| | | * @param scope |
| | | * The search scope. |
| | | * @return {@code true} if this DN matches the provided base DN and search |
| | | * scope, otherwise {@code false}. |
| | | * @throws LocalizedIllegalArgumentException |
| | | * If {@code dn} is not a valid LDAP string representation of a DN. |
| | | * @throws NullPointerException |
| | | * If {@code dn} or {@code scope} was {@code null}. |
| | | */ |
| | | public boolean isInScopeOf(String dn, SearchScope scope) |
| | | { |
| | | return isInScopeOf(valueOf(dn), scope); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns {@code true} if this DN is the immediate parent of the provided DN. |
| | | * |
| | | * @param dn |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns the DN whose content is the specified number of RDNs from this DN. |
| | | * The following equivalences hold: |
| | | * |
| | | * <pre> |
| | | * dn.localName(0).isRootDN(); |
| | | * dn.localName(1).equals(rootDN.child(dn.rdn())); |
| | | * dn.localName(dn.size()).equals(dn); |
| | | * </pre> |
| | | * |
| | | * @param index |
| | | * The number of RDNs to be included in the local name. |
| | | * @return The DN whose content is the specified number of RDNs from this DN. |
| | | * @throws IllegalArgumentException |
| | | * If {@code index} is less than zero. |
| | | */ |
| | | public DN localName(final int index) throws IllegalArgumentException |
| | | { |
| | | Validator.ensureTrue(index >= 0, "index less than zero"); |
| | | |
| | | if (index == 0) |
| | | { |
| | | return ROOT_DN; |
| | | } |
| | | else if (index >= size) |
| | | { |
| | | return this; |
| | | } |
| | | else |
| | | { |
| | | final DN localName = new DN(null, rdn, null, index); |
| | | DN nextLocalName = localName; |
| | | DN lastDN = parent; |
| | | for (int i = index - 1; i > 0; i--) |
| | | { |
| | | nextLocalName.parent = new DN(null, lastDN.rdn, null, i); |
| | | nextLocalName = nextLocalName.parent; |
| | | lastDN = lastDN.parent; |
| | | } |
| | | nextLocalName.parent = ROOT_DN; |
| | | return localName; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the DN which is the immediate parent of this DN, or {@code null} if |
| | | * this DN is the Root DN. |
| | | * <p> |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns a copy of this DN whose parent DN, {@code fromDN}, has been renamed |
| | | * to the new parent DN, {@code toDN}. If this DN is not subordinate or equal |
| | | * to {@code fromDN} then this DN is returned (i.e. the DN is not renamed). |
| | | * |
| | | * @param fromDN |
| | | * The old parent DN. |
| | | * @param toDN |
| | | * The new parent DN. |
| | | * @return The renamed DN, or this DN if no renaming was performed. |
| | | * @throws NullPointerException |
| | | * If {@code fromDN} or {@code toDN} was {@code null}. |
| | | */ |
| | | public DN rename(final DN fromDN, final DN toDN) throws NullPointerException |
| | | { |
| | | Validator.ensureNotNull(fromDN, toDN); |
| | | |
| | | if (!isSubordinateOrEqualTo(fromDN)) |
| | | { |
| | | return this; |
| | | } |
| | | else if (equals(fromDN)) |
| | | { |
| | | return toDN; |
| | | } |
| | | else |
| | | { |
| | | return toDN.child(localName(size - fromDN.size)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns the number of RDN components in this DN. |
| | | * |
| | | * @return The number of RDN components in this DN. |
| | |
| | | final DN string = DN.valueOf(stringDN); |
| | | assertEquals(raw, string); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test data for testInScopeOf tests. |
| | | * |
| | | * @return Test data. |
| | | */ |
| | | @DataProvider |
| | | public Object[][] createIsInScopeOfTestData() |
| | | { |
| | | // @formatter:off |
| | | return new Object[][] |
| | | { |
| | | { "dc=x,dc=y", "dc=x,dc=y", SearchScope.BASE_OBJECT, true }, |
| | | { "dc=x,dc=y", "dc=z,dc=y", SearchScope.BASE_OBJECT, false }, |
| | | { "dc=x,dc=z", "dc=x,dc=y", SearchScope.BASE_OBJECT, false }, |
| | | { "dc=x,dc=y", "dc=y", SearchScope.BASE_OBJECT, false }, |
| | | { "dc=y", "dc=x,dc=y", SearchScope.BASE_OBJECT, false }, |
| | | |
| | | { "dc=x,dc=y", "dc=x,dc=y", SearchScope.SINGLE_LEVEL, false }, |
| | | { "dc=x,dc=y", "dc=y", SearchScope.SINGLE_LEVEL, true }, |
| | | { "dc=z,dc=x,dc=y", "dc=y", SearchScope.SINGLE_LEVEL, false }, |
| | | { "dc=y", "dc=x,dc=y", SearchScope.SINGLE_LEVEL, false }, |
| | | { "dc=x,dc=z", "dc=y", SearchScope.SINGLE_LEVEL, false }, |
| | | |
| | | { "dc=x,dc=y", "dc=x,dc=y", SearchScope.SUBORDINATES, false }, |
| | | { "dc=x,dc=y", "dc=y", SearchScope.SUBORDINATES, true }, |
| | | { "dc=z,dc=x,dc=y", "dc=y", SearchScope.SUBORDINATES, true }, |
| | | { "dc=y", "dc=x,dc=y", SearchScope.SUBORDINATES, false }, |
| | | { "dc=x,dc=z", "dc=y", SearchScope.SUBORDINATES, false }, |
| | | |
| | | { "dc=x,dc=y", "dc=x,dc=y", SearchScope.WHOLE_SUBTREE, true }, |
| | | { "dc=x,dc=y", "dc=y", SearchScope.WHOLE_SUBTREE, true }, |
| | | { "dc=z,dc=x,dc=y", "dc=y", SearchScope.WHOLE_SUBTREE, true }, |
| | | { "dc=y", "dc=x,dc=y", SearchScope.WHOLE_SUBTREE, false }, |
| | | { "dc=x,dc=z", "dc=y", SearchScope.WHOLE_SUBTREE, false }, |
| | | }; |
| | | // @formatter:on |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests {@link DN#isInScopeOf(String, SearchScope)}. |
| | | * |
| | | * @param dn |
| | | * The target DN. |
| | | * @param baseDN |
| | | * The scope base DN. |
| | | * @param scope |
| | | * The search scope. |
| | | * @param expectedResult |
| | | * The expected result. |
| | | */ |
| | | @Test(dataProvider="createIsInScopeOfTestData") |
| | | public void testIsInScopeOfString(final String dn, final String baseDN, |
| | | final SearchScope scope, final boolean expectedResult) |
| | | { |
| | | assertEquals(DN.valueOf(dn).isInScopeOf(baseDN, scope), expectedResult); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests {@link DN#isInScopeOf(DN, SearchScope)}. |
| | | * |
| | | * @param dn |
| | | * The target DN. |
| | | * @param baseDN |
| | | * The scope base DN. |
| | | * @param scope |
| | | * The search scope. |
| | | * @param expectedResult |
| | | * The expected result. |
| | | */ |
| | | @Test(dataProvider = "createIsInScopeOfTestData") |
| | | public void testIsInScopeOfDN(final String dn, final String baseDN, |
| | | final SearchScope scope, final boolean expectedResult) |
| | | { |
| | | assertEquals(DN.valueOf(dn).isInScopeOf(DN.valueOf(baseDN), scope), |
| | | expectedResult); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test data for testLocalName tests. |
| | | * |
| | | * @return Test data. |
| | | */ |
| | | @DataProvider |
| | | public Object[][] createLocalNameTestData() |
| | | { |
| | | // @formatter:off |
| | | return new Object[][] |
| | | { |
| | | { "", 0, "" }, |
| | | { "", 1, "" }, |
| | | |
| | | { "dc=x", 0, "" }, |
| | | { "dc=x", 1, "dc=x" }, |
| | | { "dc=x", 2, "dc=x" }, |
| | | |
| | | { "dc=x,dc=y", 0, "" }, |
| | | { "dc=x,dc=y", 1, "dc=x" }, |
| | | { "dc=x,dc=y", 2, "dc=x,dc=y" }, |
| | | { "dc=x,dc=y", 3, "dc=x,dc=y" }, |
| | | |
| | | { "dc=x,dc=y,dc=z", 0, "" }, |
| | | { "dc=x,dc=y,dc=z", 1, "dc=x" }, |
| | | { "dc=x,dc=y,dc=z", 2, "dc=x,dc=y" }, |
| | | { "dc=x,dc=y,dc=z", 3, "dc=x,dc=y,dc=z" }, |
| | | { "dc=x,dc=y,dc=z", 4, "dc=x,dc=y,dc=z" }, |
| | | }; |
| | | // @formatter:on |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests {@link DN#localName(int)}. |
| | | * |
| | | * @param dn |
| | | * The DN whose local name is to be obtained. |
| | | * @param index |
| | | * The number of RDNs in the local name. |
| | | * @param expectedDN |
| | | * The expected local name. |
| | | */ |
| | | @Test(dataProvider = "createLocalNameTestData") |
| | | public void testLocalName(final String dn, final int index, |
| | | final String expectedDN) |
| | | { |
| | | assertEquals(DN.valueOf(dn).localName(index), DN.valueOf(expectedDN)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Test data for testLocalName tests. |
| | | * |
| | | * @return Test data. |
| | | */ |
| | | @DataProvider |
| | | public Object[][] createRenameTestData() |
| | | { |
| | | // @formatter:off |
| | | return new Object[][] |
| | | { |
| | | { "", "", "", "" }, |
| | | { "", "", "dc=x", "dc=x" }, |
| | | { "dc=x", "", "dc=y", "dc=x,dc=y" }, |
| | | { "dc=x", "dc=x", "dc=y", "dc=y" }, |
| | | { "dc=x,dc=y", "dc=y", "dc=z", "dc=x,dc=z" }, |
| | | { "dc=x,dc=y", "dc=x,dc=y", "dc=z", "dc=z" }, |
| | | { "dc=x,dc=y", "dc=x", "dc=z", "dc=x,dc=y" }, |
| | | }; |
| | | // @formatter:on |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests {@link DN#rename(DN, DN)}. |
| | | * |
| | | * @param dn |
| | | * The DN to be renamed. |
| | | * @param fromDN |
| | | * The source DN. |
| | | * @param toDN |
| | | * The destination DN. |
| | | * @param expectedDN |
| | | * The expected result. |
| | | */ |
| | | @Test(dataProvider = "createRenameTestData") |
| | | public void testRename(final String dn, final String fromDN, |
| | | final String toDN, final String expectedDN) |
| | | { |
| | | assertEquals(DN.valueOf(dn).rename(DN.valueOf(fromDN), DN.valueOf(toDN)), |
| | | DN.valueOf(expectedDN)); |
| | | } |
| | | } |