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-2016 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.forgerock.opendj.server.config.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  /** Creates a new instance of this HasSubordinates virtual attribute provider. */
046  public HasSubordinatesVirtualAttributeProvider()
047  {
048    super();
049
050    // All initialization should be performed in the
051    // initializeVirtualAttributeProvider method.
052  }
053
054  @Override
055  public boolean isMultiValued()
056  {
057    return false;
058  }
059
060  @Override
061  public Attribute getValues(Entry entry, VirtualAttributeRule rule)
062  {
063    Backend backend = DirectoryServer.getBackend(entry.getName());
064
065    try
066    {
067      ConditionResult ret = backend.hasSubordinates(entry.getName());
068      if(ret != null && ret != ConditionResult.UNDEFINED)
069      {
070        return Attributes.create(rule.getAttributeType(), ret.toString());
071      }
072    }
073    catch(DirectoryException de)
074    {
075      logger.traceException(de);
076    }
077
078    return Attributes.empty(rule.getAttributeType());
079  }
080
081  @Override
082  public boolean hasValue(Entry entry, VirtualAttributeRule rule)
083  {
084    Backend backend = DirectoryServer.getBackend(entry.getName());
085
086    try
087    {
088      ConditionResult ret = backend.hasSubordinates(entry.getName());
089      return ret != null && ret != ConditionResult.UNDEFINED;
090    }
091    catch(DirectoryException de)
092    {
093      logger.traceException(de);
094
095      return false;
096    }
097  }
098
099  @Override
100  public boolean hasValue(Entry entry, VirtualAttributeRule rule, ByteString value)
101  {
102    Backend backend = DirectoryServer.getBackend(entry.getName());
103    MatchingRule matchingRule =
104        rule.getAttributeType().getEqualityMatchingRule();
105
106    try
107    {
108      ByteString normValue = matchingRule.normalizeAttributeValue(value);
109      ConditionResult ret = backend.hasSubordinates(entry.getName());
110      return ret != null
111          && ret != ConditionResult.UNDEFINED
112          && ConditionResult.valueOf(normValue.toString()).equals(ret);
113    }
114    catch (Exception de)
115    {
116      logger.traceException(de);
117      return false;
118    }
119  }
120
121  @Override
122  public ConditionResult matchesSubstring(Entry entry,
123                                          VirtualAttributeRule rule,
124                                          ByteString subInitial,
125                                          List<ByteString> subAny,
126                                          ByteString subFinal)
127  {
128    // This virtual attribute does not support substring matching.
129    return ConditionResult.UNDEFINED;
130  }
131
132  @Override
133  public ConditionResult greaterThanOrEqualTo(Entry entry,
134                              VirtualAttributeRule rule,
135                              ByteString value)
136  {
137    // This virtual attribute does not support ordering matching.
138    return ConditionResult.UNDEFINED;
139  }
140
141  @Override
142  public ConditionResult lessThanOrEqualTo(Entry entry,
143                              VirtualAttributeRule rule,
144                              ByteString value)
145  {
146    // This virtual attribute does not support ordering matching.
147    return ConditionResult.UNDEFINED;
148  }
149
150  @Override
151  public ConditionResult approximatelyEqualTo(Entry entry,
152                              VirtualAttributeRule rule,
153                              ByteString value)
154  {
155    // This virtual attribute does not support approximate matching.
156    return ConditionResult.UNDEFINED;
157  }
158
159  @Override
160  public boolean isSearchable(VirtualAttributeRule rule,
161                              SearchOperation searchOperation,
162                              boolean isPreIndexed)
163  {
164    return false;
165  }
166
167  @Override
168  public void processSearch(VirtualAttributeRule rule,
169                            SearchOperation searchOperation)
170  {
171    searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
172
173    LocalizableMessage message = ERR_HASSUBORDINATES_VATTR_NOT_SEARCHABLE.get(
174            rule.getAttributeType().getNameOrOID());
175    searchOperation.appendErrorMessage(message);
176  }
177}