001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2012-2015 ForgeRock AS.
016 */
017package org.opends.server.extensions;
018
019import java.util.List;
020
021import org.forgerock.i18n.LocalizableMessage;
022import org.forgerock.i18n.slf4j.LocalizedLogger;
023import org.forgerock.opendj.ldap.ByteString;
024import org.forgerock.opendj.ldap.ConditionResult;
025import org.forgerock.opendj.ldap.ResultCode;
026import org.opends.server.admin.std.server.HasSubordinatesVirtualAttributeCfg;
027import org.opends.server.api.Backend;
028import org.forgerock.opendj.ldap.schema.MatchingRule;
029import org.opends.server.api.VirtualAttributeProvider;
030import org.opends.server.core.DirectoryServer;
031import org.opends.server.core.SearchOperation;
032import org.opends.server.types.*;
033
034import static org.opends.messages.ExtensionMessages.*;
035
036/**
037 * This class implements a virtual attribute provider that is meant to serve the
038 * hasSubordinates operational attribute as described in X.501.
039 */
040public class HasSubordinatesVirtualAttributeProvider
041       extends VirtualAttributeProvider<HasSubordinatesVirtualAttributeCfg>
042{
043  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
044
045  /**
046   * Creates a new instance of this HasSubordinates virtual attribute provider.
047   */
048  public HasSubordinatesVirtualAttributeProvider()
049  {
050    super();
051
052    // All initialization should be performed in the
053    // initializeVirtualAttributeProvider method.
054  }
055
056  /** {@inheritDoc} */
057  @Override
058  public boolean isMultiValued()
059  {
060    return false;
061  }
062
063  /** {@inheritDoc} */
064  @Override
065  public Attribute getValues(Entry entry, VirtualAttributeRule rule)
066  {
067    Backend backend = DirectoryServer.getBackend(entry.getName());
068
069    try
070    {
071      ConditionResult ret = backend.hasSubordinates(entry.getName());
072      if(ret != null && ret != ConditionResult.UNDEFINED)
073      {
074        return Attributes.create(rule.getAttributeType(), ret.toString());
075      }
076    }
077    catch(DirectoryException de)
078    {
079      logger.traceException(de);
080    }
081
082    return Attributes.empty(rule.getAttributeType());
083  }
084
085  /** {@inheritDoc} */
086  @Override
087  public boolean hasValue(Entry entry, VirtualAttributeRule rule)
088  {
089    Backend backend = DirectoryServer.getBackend(entry.getName());
090
091    try
092    {
093      ConditionResult ret = backend.hasSubordinates(entry.getName());
094      return ret != null && ret != ConditionResult.UNDEFINED;
095    }
096    catch(DirectoryException de)
097    {
098      logger.traceException(de);
099
100      return false;
101    }
102  }
103
104  /** {@inheritDoc} */
105  @Override
106  public boolean hasValue(Entry entry, VirtualAttributeRule rule, ByteString value)
107  {
108    Backend backend = DirectoryServer.getBackend(entry.getName());
109    MatchingRule matchingRule =
110        rule.getAttributeType().getEqualityMatchingRule();
111
112    try
113    {
114      ByteString normValue = matchingRule.normalizeAttributeValue(value);
115      ConditionResult ret = backend.hasSubordinates(entry.getName());
116      return ret != null
117          && ret != ConditionResult.UNDEFINED
118          && ConditionResult.valueOf(normValue.toString()).equals(ret);
119    }
120    catch (Exception de)
121    {
122      logger.traceException(de);
123      return false;
124    }
125  }
126
127  /** {@inheritDoc} */
128  @Override
129  public ConditionResult matchesSubstring(Entry entry,
130                                          VirtualAttributeRule rule,
131                                          ByteString subInitial,
132                                          List<ByteString> subAny,
133                                          ByteString subFinal)
134  {
135    // This virtual attribute does not support substring matching.
136    return ConditionResult.UNDEFINED;
137  }
138
139  /** {@inheritDoc} */
140  @Override
141  public ConditionResult greaterThanOrEqualTo(Entry entry,
142                              VirtualAttributeRule rule,
143                              ByteString value)
144  {
145    // This virtual attribute does not support ordering matching.
146    return ConditionResult.UNDEFINED;
147  }
148
149  /** {@inheritDoc} */
150  @Override
151  public ConditionResult lessThanOrEqualTo(Entry entry,
152                              VirtualAttributeRule rule,
153                              ByteString value)
154  {
155    // This virtual attribute does not support ordering matching.
156    return ConditionResult.UNDEFINED;
157  }
158
159  /** {@inheritDoc} */
160  @Override
161  public ConditionResult approximatelyEqualTo(Entry entry,
162                              VirtualAttributeRule rule,
163                              ByteString value)
164  {
165    // This virtual attribute does not support approximate matching.
166    return ConditionResult.UNDEFINED;
167  }
168
169  /** {@inheritDoc} */
170  @Override
171  public boolean isSearchable(VirtualAttributeRule rule,
172                              SearchOperation searchOperation,
173                              boolean isPreIndexed)
174  {
175    return false;
176  }
177
178  /** {@inheritDoc} */
179  @Override
180  public void processSearch(VirtualAttributeRule rule,
181                            SearchOperation searchOperation)
182  {
183    searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
184
185    LocalizableMessage message = ERR_HASSUBORDINATES_VATTR_NOT_SEARCHABLE.get(
186            rule.getAttributeType().getNameOrOID());
187    searchOperation.appendErrorMessage(message);
188  }
189}
190