| | |
| | | * Copyright 2008-2009 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | |
| | | package org.opends.server.schema; |
| | | |
| | | |
| | | |
| | | import static org.opends.messages.ConfigMessages.*; |
| | | import static org.opends.messages.CoreMessages.*; |
| | | import static org.opends.messages.SchemaMessages.*; |
| | | import static org.opends.server.loggers.ErrorLogger.*; |
| | | import static org.opends.server.schema.SchemaConstants.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | import java.nio.CharBuffer; |
| | | import java.text.CollationKey; |
| | | import java.text.Collator; |
| | | import java.nio.CharBuffer; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.SortedSet; |
| | | import java.util.TreeSet; |
| | | |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.meta.CollationMatchingRuleCfgDefn. |
| | | MatchingRuleType; |
| | | import org.opends.server.api.ExtensibleIndexer; |
| | | import org.opends.server.api.IndexQueryFactory; |
| | | import org.opends.server.api.MatchingRuleFactory; |
| | | import org.opends.server.admin.std.meta. |
| | | CollationMatchingRuleCfgDefn.MatchingRuleType; |
| | | import org.opends.server.admin.std.server.CollationMatchingRuleCfg; |
| | | import org.opends.server.api.ExtensibleIndexer; |
| | | import org.opends.server.api.ExtensibleMatchingRule; |
| | | import org.opends.server.api.IndexQueryFactory; |
| | | import org.opends.server.api.MatchingRule; |
| | | import org.opends.server.api.MatchingRuleFactory; |
| | | import org.opends.server.backends.jeb.AttributeIndex; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteSequence; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.IndexConfig; |
| | | import org.opends.server.types.InitializationException; |
| | | |
| | | import org.opends.server.types.ResultCode; |
| | | import static org.opends.server.schema.SchemaConstants.*; |
| | | import static org.opends.server.loggers.ErrorLogger.logError; |
| | | import static org.opends.messages.SchemaMessages.*; |
| | | import static org.opends.messages.CoreMessages.*; |
| | | import static org.opends.messages.ConfigMessages.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | import static org.opends.server.api.ExtensibleIndexer.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class is a factory class for Collation matching rules. It creates |
| | | * different matching rules based on the configuration entries. |
| | | * This class is a factory class for Collation matching rules. It |
| | | * creates different matching rules based on the configuration entries. |
| | | */ |
| | | public final class CollationMatchingRuleFactory |
| | | extends MatchingRuleFactory<CollationMatchingRuleCfg> |
| | | implements ConfigurationChangeListener<CollationMatchingRuleCfg> |
| | | public final class CollationMatchingRuleFactory extends |
| | | MatchingRuleFactory<CollationMatchingRuleCfg> implements |
| | | ConfigurationChangeListener<CollationMatchingRuleCfg> |
| | | { |
| | | |
| | | //Whether equality matching rules are enabled. |
| | | // Whether equality matching rules are enabled. |
| | | private boolean equalityMatchingRuleType; |
| | | |
| | | //Whether less-than matching rules are enabled. |
| | | // Whether less-than matching rules are enabled. |
| | | private boolean lessThanMatchingRuleType; |
| | | |
| | | //Whether less-than-equal-to matching rules are enabled. |
| | | // Whether less-than-equal-to matching rules are enabled. |
| | | private boolean lessThanEqualToMatchingRuleType; |
| | | |
| | | //Whether less-than-equal-to matching rules are enabled. |
| | | // Whether less-than-equal-to matching rules are enabled. |
| | | private boolean greaterThanMatchingRuleType; |
| | | |
| | | //Whether greater-than matching rules are enabled. |
| | | // Whether greater-than matching rules are enabled. |
| | | private boolean greaterThanEqualToMatchingRuleType; |
| | | |
| | | //Whether greater-than-equal-to matching rules are enabled. |
| | | // Whether greater-than-equal-to matching rules are enabled. |
| | | private boolean substringMatchingRuleType; |
| | | |
| | | //Stores the list of available locales on this JVM. |
| | | // Stores the list of available locales on this JVM. |
| | | private static final Set<Locale> supportedLocales; |
| | | |
| | | //Current Configuration. |
| | | // Current Configuration. |
| | | private CollationMatchingRuleCfg currentConfig; |
| | | |
| | | //Map of OID and the Matching Rule. |
| | | private final Map<String, MatchingRule> matchingRules; |
| | | |
| | | // Map of OID and the Matching Rule. |
| | | private final Map<String, MatchingRule> matchingRules; |
| | | |
| | | static |
| | | { |
| | | supportedLocales = new HashSet<Locale>(); |
| | | for(Locale l:Locale.getAvailableLocales()) |
| | | for (Locale l : Locale.getAvailableLocales()) |
| | | { |
| | | supportedLocales.add(l); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of CollationMatchingRuleFactory. |
| | | */ |
| | | public CollationMatchingRuleFactory() |
| | | { |
| | | //Initialize the matchingRules. |
| | | matchingRules = new HashMap<String,MatchingRule>(); |
| | | // Initialize the matchingRules. |
| | | matchingRules = new HashMap<String, MatchingRule>(); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * Adds a new mapping of OID and MatchingRule. |
| | | * |
| | | * @param oid OID of the matching rule |
| | | * @param matchingRule instance of a MatchingRule. |
| | | * @param oid |
| | | * OID of the matching rule |
| | | * @param matchingRule |
| | | * instance of a MatchingRule. |
| | | */ |
| | | private final void addMatchingRule(String oid, |
| | | MatchingRule matchingRule) |
| | | MatchingRule matchingRule) |
| | | { |
| | | matchingRules.put(oid, matchingRule); |
| | | } |
| | |
| | | /** |
| | | * Returns the Matching rule for the specified OID. |
| | | * |
| | | * @param oid OID of the matching rule to be searched. |
| | | * @return MatchingRule corresponding to an OID. |
| | | * @param oid |
| | | * OID of the matching rule to be searched. |
| | | * @return MatchingRule corresponding to an OID. |
| | | */ |
| | | private final MatchingRule getMatchingRule(String oid) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Clears the Map containing matching Rules. |
| | | */ |
| | |
| | | /** |
| | | * Reads the configuration and initializes matching rule types. |
| | | * |
| | | * @param ruleTypes The Set containing allowed matching rule types. |
| | | * @param ruleTypes |
| | | * The Set containing allowed matching rule types. |
| | | */ |
| | | private void initializeMatchingRuleTypes(SortedSet<MatchingRuleType> |
| | | ruleTypes) |
| | | private void initializeMatchingRuleTypes( |
| | | SortedSet<MatchingRuleType> ruleTypes) |
| | | { |
| | | for(MatchingRuleType type:ruleTypes) |
| | | for (MatchingRuleType type : ruleTypes) |
| | | { |
| | | switch(type) |
| | | switch (type) |
| | | { |
| | | case EQUALITY: |
| | | equalityMatchingRuleType = true; |
| | | break; |
| | | case LESS_THAN: |
| | | lessThanMatchingRuleType = true; |
| | | break; |
| | | case LESS_THAN_OR_EQUAL_TO: |
| | | lessThanEqualToMatchingRuleType = true; |
| | | break; |
| | | case GREATER_THAN: |
| | | greaterThanMatchingRuleType = true; |
| | | break; |
| | | case GREATER_THAN_OR_EQUAL_TO: |
| | | greaterThanEqualToMatchingRuleType = true; |
| | | break; |
| | | case SUBSTRING: |
| | | substringMatchingRuleType = true; |
| | | break; |
| | | default: |
| | | //No default values allowed. |
| | | case EQUALITY: |
| | | equalityMatchingRuleType = true; |
| | | break; |
| | | case LESS_THAN: |
| | | lessThanMatchingRuleType = true; |
| | | break; |
| | | case LESS_THAN_OR_EQUAL_TO: |
| | | lessThanEqualToMatchingRuleType = true; |
| | | break; |
| | | case GREATER_THAN: |
| | | greaterThanMatchingRuleType = true; |
| | | break; |
| | | case GREATER_THAN_OR_EQUAL_TO: |
| | | greaterThanEqualToMatchingRuleType = true; |
| | | break; |
| | | case SUBSTRING: |
| | | substringMatchingRuleType = true; |
| | | break; |
| | | default: |
| | | // No default values allowed. |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * Creates a new Collator instance. |
| | | * |
| | | * @param locale Locale for the collator |
| | | * @param locale |
| | | * Locale for the collator |
| | | * @return Returns a new Collator instance |
| | | */ |
| | | private Collator createCollator(Locale locale) |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void initializeMatchingRule(CollationMatchingRuleCfg configuration) |
| | | throws ConfigException, InitializationException |
| | | public void initializeMatchingRule( |
| | | CollationMatchingRuleCfg configuration) throws ConfigException, |
| | | InitializationException |
| | | { |
| | | initializeMatchingRuleTypes(configuration.getMatchingRuleType()); |
| | | for(String collation:configuration.getCollation()) |
| | | for (String collation : configuration.getCollation()) |
| | | { |
| | | CollationMapper mapper = new CollationMapper(collation); |
| | | |
| | | String nOID = mapper.getNumericOID(); |
| | | String languageTag = mapper.getLanguageTag(); |
| | | if(nOID==null || languageTag==null) |
| | | if (nOID == null || languageTag == null) |
| | | { |
| | | Message msg = |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_FORMAT. |
| | | get(collation); |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_FORMAT |
| | | .get(collation); |
| | | logError(msg); |
| | | continue; |
| | | } |
| | | |
| | | Locale locale = getLocale(languageTag); |
| | | if(locale!=null) |
| | | if (locale != null) |
| | | { |
| | | createLessThanMatchingRule(mapper,locale); |
| | | createLessThanOrEqualToMatchingRule(mapper,locale); |
| | | createEqualityMatchingRule(mapper,locale); |
| | | createGreaterThanOrEqualToMatchingRule(mapper,locale); |
| | | createGreaterThanMatchingRule(mapper,locale); |
| | | createSubstringMatchingRule(mapper,locale); |
| | | createLessThanMatchingRule(mapper, locale); |
| | | createLessThanOrEqualToMatchingRule(mapper, locale); |
| | | createEqualityMatchingRule(mapper, locale); |
| | | createGreaterThanOrEqualToMatchingRule(mapper, locale); |
| | | createGreaterThanMatchingRule(mapper, locale); |
| | | createSubstringMatchingRule(mapper, locale); |
| | | } |
| | | else |
| | | { |
| | | //This locale is not supported by JVM. |
| | | // This locale is not supported by JVM. |
| | | Message msg = |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_LOCALE. |
| | | get(collation,configuration.dn().toNormalizedString(), |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_LOCALE.get( |
| | | collation, configuration.dn().toNormalizedString(), |
| | | languageTag); |
| | | |
| | | logError(msg); |
| | | } |
| | | } |
| | | //Save this configuration. |
| | | |
| | | // Save this configuration. |
| | | currentConfig = configuration; |
| | | //Register for change events. |
| | | |
| | | // Register for change events. |
| | | currentConfig.addCollationChangeListener(this); |
| | | } |
| | | |
| | |
| | | @Override |
| | | public void finalizeMatchingRule() |
| | | { |
| | | //De-register the listener. |
| | | // De-register the listener. |
| | | currentConfig.removeCollationChangeListener(this); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | CollationMatchingRuleCfg configuration) |
| | | CollationMatchingRuleCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<Message> messages = new ArrayList<Message>(); |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<Message> messages = new ArrayList<Message>(); |
| | | |
| | | if(!configuration.isEnabled() || |
| | | currentConfig.isEnabled()!=configuration.isEnabled()) |
| | | if (!configuration.isEnabled() |
| | | || currentConfig.isEnabled() != configuration.isEnabled()) |
| | | { |
| | | //Don't do anything if: |
| | | // Don't do anything if: |
| | | // 1. The configuration is disabled. |
| | | // 2. There is a change in the enable status |
| | | // i.e. (disable->enable or enable->disable). In this case, the |
| | | // ConfigManager will have already created the new Factory object. |
| | | return new ConfigChangeResult(resultCode, |
| | | adminActionRequired, messages); |
| | | // i.e. (disable->enable or enable->disable). In this case, the |
| | | // ConfigManager will have already created the new Factory object. |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | //Since we have come here it means that this Factory is enabled and |
| | | //there is a change in the CollationMatchingRuleFactory's configuration. |
| | | // Deregister all the Matching Rule corresponding to this factory.. |
| | | for(MatchingRule rule: getMatchingRules()) |
| | | // Since we have come here it means that this Factory is enabled and |
| | | // there is a change in the CollationMatchingRuleFactory's |
| | | // configuration. |
| | | // Deregister all the Matching Rule corresponding to this factory. |
| | | for (MatchingRule rule : getMatchingRules()) |
| | | { |
| | | DirectoryServer.deregisterMatchingRule(rule); |
| | | } |
| | | //Clear the associated matching rules. |
| | | |
| | | // Clear the associated matching rules. |
| | | resetRules(); |
| | | |
| | | initializeMatchingRuleTypes(configuration.getMatchingRuleType()); |
| | | for(String collation:configuration.getCollation()) |
| | | for (String collation : configuration.getCollation()) |
| | | { |
| | | CollationMapper mapper = new CollationMapper(collation); |
| | | String languageTag = mapper.getLanguageTag(); |
| | | Locale locale = getLocale(languageTag); |
| | | createLessThanMatchingRule(mapper,locale); |
| | | createLessThanOrEqualToMatchingRule(mapper,locale); |
| | | createEqualityMatchingRule(mapper,locale); |
| | | createGreaterThanOrEqualToMatchingRule(mapper,locale); |
| | | createGreaterThanMatchingRule(mapper,locale); |
| | | createSubstringMatchingRule(mapper,locale); |
| | | createLessThanMatchingRule(mapper, locale); |
| | | createLessThanOrEqualToMatchingRule(mapper, locale); |
| | | createEqualityMatchingRule(mapper, locale); |
| | | createGreaterThanOrEqualToMatchingRule(mapper, locale); |
| | | createGreaterThanMatchingRule(mapper, locale); |
| | | createSubstringMatchingRule(mapper, locale); |
| | | } |
| | | |
| | | try |
| | | { |
| | | for(MatchingRule matchingRule: getMatchingRules()) |
| | | for (MatchingRule matchingRule : getMatchingRules()) |
| | | { |
| | | DirectoryServer.registerMatchingRule(matchingRule, false); |
| | | } |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | Message message = WARN_CONFIG_SCHEMA_MR_CONFLICTING_MR.get( |
| | | String.valueOf(configuration.dn()), de.getMessageObject()); |
| | | Message message = |
| | | WARN_CONFIG_SCHEMA_MR_CONFLICTING_MR.get(String |
| | | .valueOf(configuration.dn()), de.getMessageObject()); |
| | | adminActionRequired = true; |
| | | messages.add(message); |
| | | } |
| | | currentConfig = configuration; |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, |
| | | messages); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | CollationMatchingRuleCfg configuration, |
| | | List<Message> unacceptableReasons) |
| | | CollationMatchingRuleCfg configuration, |
| | | List<Message> unacceptableReasons) |
| | | { |
| | | boolean configAcceptable = true; |
| | | |
| | | //If the new configuration disables this factory, don't do anything. |
| | | if(!configuration.isEnabled()) |
| | | // If the new configuration disables this factory, don't do |
| | | // anything. |
| | | if (!configuration.isEnabled()) |
| | | { |
| | | return configAcceptable; |
| | | } |
| | | |
| | | |
| | | //If it comes here we don't need to verify MatchingRuleType; it should be |
| | | //okay as its syntax is verified by the admin framework. Iterate over the |
| | | //collations and verify if the format is okay. Also, verify if the |
| | | //locale is allowed by the JVM. |
| | | for(String collation:configuration.getCollation()) |
| | | // If it comes here we don't need to verify MatchingRuleType; it |
| | | // should be okay as its syntax is verified by the admin framework. |
| | | // Iterate over the collations and verify if the format is okay. |
| | | // Also, |
| | | // verify if the locale is allowed by the JVM. |
| | | for (String collation : configuration.getCollation()) |
| | | { |
| | | CollationMapper mapper = new CollationMapper(collation); |
| | | |
| | | String nOID = mapper.getNumericOID(); |
| | | String languageTag = mapper.getLanguageTag(); |
| | | if(nOID==null || languageTag==null) |
| | | if (nOID == null || languageTag == null) |
| | | { |
| | | configAcceptable = false; |
| | | Message msg = |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_FORMAT. |
| | | get(collation); |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_FORMAT |
| | | .get(collation); |
| | | unacceptableReasons.add(msg); |
| | | continue; |
| | | } |
| | | |
| | | Locale locale = getLocale(languageTag); |
| | | if(locale==null) |
| | | if (locale == null) |
| | | { |
| | | Message msg = |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_LOCALE. |
| | | get(collation,configuration.dn().toNormalizedString(), |
| | | WARN_ATTR_INVALID_COLLATION_MATCHING_RULE_LOCALE.get( |
| | | collation, configuration.dn().toNormalizedString(), |
| | | languageTag); |
| | | unacceptableReasons.add(msg); |
| | | configAcceptable = false; |
| | |
| | | /** |
| | | * Creates Less-than Matching Rule. |
| | | * |
| | | * @param mapper CollationMapper containing OID and the language Tag. |
| | | * @param locale Locale value |
| | | * @param mapper |
| | | * CollationMapper containing OID and the language Tag. |
| | | * @param locale |
| | | * Locale value |
| | | */ |
| | | private void createLessThanMatchingRule(CollationMapper mapper,Locale locale) |
| | | private void createLessThanMatchingRule(CollationMapper mapper, |
| | | Locale locale) |
| | | { |
| | | if(!lessThanMatchingRuleType) |
| | | return; |
| | | if (!lessThanMatchingRuleType) return; |
| | | |
| | | String oid = mapper.getNumericOID()+".1"; |
| | | String oid = mapper.getNumericOID() + ".1"; |
| | | String lTag = mapper.getLanguageTag(); |
| | | |
| | | Collection<String> names = new HashSet<String>(); |
| | | MatchingRule matchingRule = getMatchingRule(oid); |
| | | if(matchingRule!=null) |
| | | if (matchingRule != null) |
| | | { |
| | | for(String name: matchingRule.getAllNames()) |
| | | for (String name : matchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | | } |
| | | |
| | | names.add(lTag+".lt"); |
| | | names.add(lTag + ".lt"); |
| | | names.add(lTag + ".1"); |
| | | |
| | | matchingRule = new CollationLessThanMatchingRule(oid, names, locale); |
| | | matchingRule = |
| | | new CollationLessThanMatchingRule(oid, names, locale); |
| | | addMatchingRule(oid, matchingRule); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Creates Less-Than-Equal-To Matching Rule. |
| | | * |
| | | * @param mapper CollationMapper containing OID and the language Tag. |
| | | * @param locale Locale value |
| | | * @param mapper |
| | | * CollationMapper containing OID and the language Tag. |
| | | * @param locale |
| | | * Locale value |
| | | */ |
| | | private void createLessThanOrEqualToMatchingRule(CollationMapper mapper, |
| | | Locale locale) |
| | | private void createLessThanOrEqualToMatchingRule( |
| | | CollationMapper mapper, Locale locale) |
| | | { |
| | | if(!lessThanEqualToMatchingRuleType) |
| | | return; |
| | | if (!lessThanEqualToMatchingRuleType) return; |
| | | |
| | | String oid = mapper.getNumericOID()+".2"; |
| | | String oid = mapper.getNumericOID() + ".2"; |
| | | String lTag = mapper.getLanguageTag(); |
| | | |
| | | Collection<String> names = new HashSet<String>(); |
| | | MatchingRule matchingRule = getMatchingRule(oid); |
| | | if(matchingRule!=null) |
| | | if (matchingRule != null) |
| | | { |
| | | for(String name: matchingRule.getAllNames()) |
| | | for (String name : matchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | | } |
| | | |
| | | names.add(lTag+".lte"); |
| | | names.add(lTag + ".lte"); |
| | | names.add(lTag + ".2"); |
| | | |
| | | matchingRule = |
| | | new CollationLessThanOrEqualToMatchingRule(oid,names,locale); |
| | | new CollationLessThanOrEqualToMatchingRule(oid, names, locale); |
| | | addMatchingRule(oid, matchingRule); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Creates Equality Matching Rule. |
| | | * |
| | | * @param mapper CollationMapper containing OID and the language Tag. |
| | | * @param locale Locale value |
| | | * @param mapper |
| | | * CollationMapper containing OID and the language Tag. |
| | | * @param locale |
| | | * Locale value |
| | | */ |
| | | private void createEqualityMatchingRule(CollationMapper mapper,Locale locale) |
| | | private void createEqualityMatchingRule(CollationMapper mapper, |
| | | Locale locale) |
| | | { |
| | | if(!equalityMatchingRuleType) |
| | | if (!equalityMatchingRuleType) |
| | | { |
| | | return; |
| | | //Register the default OID as equality matching rule. |
| | | } |
| | | |
| | | // Register the default OID as equality matching rule. |
| | | String lTag = mapper.getLanguageTag(); |
| | | String nOID = mapper.getNumericOID(); |
| | | |
| | | MatchingRule matchingRule = getMatchingRule(nOID); |
| | | Collection<String> names = new HashSet<String>(); |
| | | if(matchingRule!=null) |
| | | if (matchingRule != null) |
| | | { |
| | | for(String name: matchingRule.getAllNames()) |
| | | for (String name : matchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | |
| | | |
| | | names.add(lTag); |
| | | matchingRule = |
| | | new CollationEqualityMatchingRule(nOID, |
| | | Collections.<String>emptySet(),locale); |
| | | new CollationEqualityMatchingRule(nOID, Collections |
| | | .<String> emptySet(), locale); |
| | | addMatchingRule(nOID, matchingRule); |
| | | |
| | | // Register OID.3 as the equality matching rule. |
| | | String OID = mapper.getNumericOID() + ".3"; |
| | | MatchingRule equalityMatchingRule = getMatchingRule(OID); |
| | | if(equalityMatchingRule!=null) |
| | | if (equalityMatchingRule != null) |
| | | { |
| | | for(String name: equalityMatchingRule.getAllNames()) |
| | | for (String name : equalityMatchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | | } |
| | | |
| | | names.add(lTag+".eq"); |
| | | names.add(lTag+".3"); |
| | | names.add(lTag + ".eq"); |
| | | names.add(lTag + ".3"); |
| | | |
| | | equalityMatchingRule = |
| | | new CollationEqualityMatchingRule(OID,names,locale); |
| | | new CollationEqualityMatchingRule(OID, names, locale); |
| | | addMatchingRule(OID, equalityMatchingRule); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Creates Greater-than-equal-to Matching Rule. |
| | | * |
| | | * @param mapper CollationMapper containing OID and the language Tag. |
| | | * @param locale Locale value |
| | | * @param mapper |
| | | * CollationMapper containing OID and the language Tag. |
| | | * @param locale |
| | | * Locale value |
| | | */ |
| | | private void createGreaterThanOrEqualToMatchingRule(CollationMapper mapper, |
| | | Locale locale) |
| | | private void createGreaterThanOrEqualToMatchingRule( |
| | | CollationMapper mapper, Locale locale) |
| | | { |
| | | if(!greaterThanEqualToMatchingRuleType) |
| | | return; |
| | | if (!greaterThanEqualToMatchingRuleType) return; |
| | | |
| | | String oid = mapper.getNumericOID()+".4"; |
| | | String oid = mapper.getNumericOID() + ".4"; |
| | | String lTag = mapper.getLanguageTag(); |
| | | |
| | | Collection<String> names = new HashSet<String>(); |
| | | MatchingRule matchingRule = getMatchingRule(oid); |
| | | if(matchingRule!=null) |
| | | if (matchingRule != null) |
| | | { |
| | | for(String name: matchingRule.getAllNames()) |
| | | for (String name : matchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | | } |
| | | |
| | | names.add(lTag+".gte"); |
| | | names.add(lTag + ".gte"); |
| | | names.add(lTag + ".4"); |
| | | matchingRule = |
| | | new CollationGreaterThanOrEqualToMatchingRule(oid,names,locale); |
| | | new CollationGreaterThanOrEqualToMatchingRule(oid, names, |
| | | locale); |
| | | addMatchingRule(oid, matchingRule); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Creates Greater-than Matching Rule. |
| | | * |
| | | * @param mapper CollationMapper containing OID and the language Tag. |
| | | * @param locale Locale value |
| | | * @param mapper |
| | | * CollationMapper containing OID and the language Tag. |
| | | * @param locale |
| | | * Locale value |
| | | */ |
| | | private void createGreaterThanMatchingRule(CollationMapper mapper, |
| | | Locale locale) |
| | | Locale locale) |
| | | { |
| | | if(!greaterThanMatchingRuleType) |
| | | return; |
| | | if (!greaterThanMatchingRuleType) return; |
| | | |
| | | String oid = mapper.getNumericOID()+".5"; |
| | | String oid = mapper.getNumericOID() + ".5"; |
| | | String lTag = mapper.getLanguageTag(); |
| | | |
| | | Collection<String> names = new HashSet<String>(); |
| | | MatchingRule matchingRule = getMatchingRule(oid); |
| | | if(matchingRule!=null) |
| | | if (matchingRule != null) |
| | | { |
| | | for(String name: matchingRule.getAllNames()) |
| | | for (String name : matchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | | } |
| | | |
| | | names.add(lTag+".gt"); |
| | | names.add(lTag + ".gt"); |
| | | names.add(lTag + ".5"); |
| | | matchingRule = |
| | | new CollationGreaterThanMatchingRule(oid,names,locale); |
| | | new CollationGreaterThanMatchingRule(oid, names, locale); |
| | | addMatchingRule(oid, matchingRule); |
| | | } |
| | | |
| | |
| | | /** |
| | | * Creates substring Matching Rule. |
| | | * |
| | | * @param mapper CollationMapper containing OID and the language Tag. |
| | | * @param locale Locale value |
| | | * @param mapper |
| | | * CollationMapper containing OID and the language Tag. |
| | | * @param locale |
| | | * Locale value |
| | | */ |
| | | private void createSubstringMatchingRule(CollationMapper mapper,Locale locale) |
| | | private void createSubstringMatchingRule(CollationMapper mapper, |
| | | Locale locale) |
| | | { |
| | | if(!substringMatchingRuleType) |
| | | return; |
| | | if (!substringMatchingRuleType) return; |
| | | |
| | | String oid = mapper.getNumericOID()+".6"; |
| | | String oid = mapper.getNumericOID() + ".6"; |
| | | String lTag = mapper.getLanguageTag(); |
| | | |
| | | Collection<String> names = new HashSet<String>(); |
| | | MatchingRule matchingRule = getMatchingRule(oid); |
| | | if(matchingRule!=null) |
| | | if (matchingRule != null) |
| | | { |
| | | for(String name: matchingRule.getAllNames()) |
| | | for (String name : matchingRule.getAllNames()) |
| | | { |
| | | names.add(name); |
| | | } |
| | | } |
| | | names.add(lTag+".sub"); |
| | | names.add(lTag + ".sub"); |
| | | names.add(lTag + ".6"); |
| | | matchingRule = |
| | | new CollationSubstringMatchingRule(oid,names,locale); |
| | | new CollationSubstringMatchingRule(oid, names, locale); |
| | | addMatchingRule(oid, matchingRule); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Verifies if the locale is supported by the JVM. |
| | | * |
| | | * @param lTag The language tag specified in the configuration. |
| | | * @return Locale The locale correspoding to the languageTag. |
| | | * @param lTag |
| | | * The language tag specified in the configuration. |
| | | * @return Locale The locale correspoding to the languageTag. |
| | | */ |
| | | private Locale getLocale(String lTag) |
| | | { |
| | | //Separates the language and the country from the locale. |
| | | // Separates the language and the country from the locale. |
| | | Locale locale; |
| | | String lang = null; |
| | | String country = null; |
| | |
| | | int countryIndex = lTag.indexOf("-"); |
| | | int variantIndex = lTag.lastIndexOf("-"); |
| | | |
| | | if(countryIndex > 0) |
| | | if (countryIndex > 0) |
| | | { |
| | | lang = lTag.substring(0,countryIndex); |
| | | lang = lTag.substring(0, countryIndex); |
| | | |
| | | if(variantIndex>countryIndex) |
| | | if (variantIndex > countryIndex) |
| | | { |
| | | country = lTag.substring(countryIndex+1,variantIndex); |
| | | variant = lTag.substring(variantIndex+1,lTag.length()); |
| | | locale = new Locale(lang,country,variant); |
| | | country = lTag.substring(countryIndex + 1, variantIndex); |
| | | variant = lTag.substring(variantIndex + 1, lTag.length()); |
| | | locale = new Locale(lang, country, variant); |
| | | } |
| | | else |
| | | { |
| | | country = lTag.substring(countryIndex+1,lTag.length()); |
| | | locale = new Locale(lang,country); |
| | | country = lTag.substring(countryIndex + 1, lTag.length()); |
| | | locale = new Locale(lang, country); |
| | | } |
| | | } |
| | | else |
| | |
| | | locale = new Locale(lTag); |
| | | } |
| | | |
| | | if(!supportedLocales.contains(locale)) |
| | | if (!supportedLocales.contains(locale)) |
| | | { |
| | | //This locale is not supported by this JVM. |
| | | // This locale is not supported by this JVM. |
| | | locale = null; |
| | | } |
| | | return locale; |
| | |
| | | /** |
| | | * Collation Extensible matching rule. |
| | | */ |
| | | private abstract class CollationMatchingRule |
| | | extends ExtensibleMatchingRule |
| | | private abstract class CollationMatchingRule extends |
| | | ExtensibleMatchingRule |
| | | { |
| | | //Names for this class. |
| | | // Names for this class. |
| | | private final Collection<String> names; |
| | | |
| | | |
| | | |
| | | //Collator for performing equality match. |
| | | // Collator for performing equality match. |
| | | protected final Collator collator; |
| | | |
| | | |
| | | |
| | | //Numeric OID of the rule. |
| | | // Numeric OID of the rule. |
| | | private final String nOID; |
| | | |
| | | |
| | | |
| | | //Locale associated with this rule. |
| | | // Locale associated with this rule. |
| | | private final Locale locale; |
| | | |
| | | |
| | | |
| | | //Indexer of this rule. |
| | | // Indexer of this rule. |
| | | protected ExtensibleIndexer indexer; |
| | | |
| | | |
| | |
| | | /** |
| | | * Constructs a new CollationMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationMatchingRule(String nOID,Collection<String> names, |
| | | Locale locale) |
| | | private CollationMatchingRule(String nOID, |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(); |
| | | this.names = names; |
| | | this.collator = createCollator(locale); |
| | | this.locale = locale; |
| | |
| | | @Override |
| | | public String getName() |
| | | { |
| | | //Concatenate all the names and return. |
| | | // Concatenate all the names and return. |
| | | StringBuilder builder = new StringBuilder(); |
| | | for(String name: getAllNames()) |
| | | for (String name : getAllNames()) |
| | | { |
| | | builder.append(name); |
| | | builder.append("\b"); |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns the name of the index database for this matching rule. |
| | | * An index name for this rule will be based upon the Locale. This will |
| | | * ensure that multiple collation matching rules corresponding to the same |
| | | * Locale can share the same index database. |
| | | * @return The name of the index for this matching rule. |
| | | */ |
| | | * Returns the name of the index database for this matching rule. An |
| | | * index name for this rule will be based upon the Locale. This will |
| | | * ensure that multiple collation matching rules corresponding to |
| | | * the same Locale can share the same index database. |
| | | * |
| | | * @return The name of the index for this matching rule. |
| | | */ |
| | | public String getIndexName() |
| | | { |
| | | String language = locale.getLanguage(); |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public Collection<ExtensibleIndexer> getIndexers(IndexConfig config) |
| | | { |
| | | if(indexer == null) |
| | | if (indexer == null) |
| | | { |
| | | //The default implementation contains shared indexer and doesn't use the |
| | | //config. |
| | | // The default implementation contains shared indexer and |
| | | // doesn't use the config. |
| | | indexer = new CollationSharedExtensibleIndexer(this); |
| | | } |
| | | return Collections.singletonList(indexer); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | *Collation rule for Equality matching rule. |
| | | * Collation rule for Equality matching rule. |
| | | */ |
| | | private final class CollationEqualityMatchingRule |
| | | extends CollationMatchingRule |
| | | private final class CollationEqualityMatchingRule extends |
| | | CollationMatchingRule |
| | | { |
| | | /** |
| | | * Constructs a new CollationEqualityMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationEqualityMatchingRule(String nOID,Collection<String> names, |
| | | Locale locale) |
| | | private CollationEqualityMatchingRule(String nOID, |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID,names,locale); |
| | | super(nOID, names, locale); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ByteString normalizeValue(ByteString value) |
| | | throws DirectoryException |
| | | public ByteString normalizeValue(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | CollationKey key = collator.getCollationKey(value.stringValue()); |
| | | return new ASN1OctetString(key.toByteArray()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the two provided normalized values are equal to |
| | | * each other. |
| | | * |
| | | * @param value1 The normalized form of the first value to |
| | | * compare. |
| | | * @param value2 The normalized form of the second value to |
| | | * compare. |
| | | * |
| | | * @return {@code true} if the provided values are equal, or |
| | | * {@code false} if not. |
| | | */ |
| | | private boolean areEqual(ByteString value1, ByteString value2) |
| | | { |
| | | return Arrays.equals(value1.value(), value2.value()); |
| | | CollationKey key = collator.getCollationKey(value.toString()); |
| | | return ByteString.wrap(key.toByteArray()); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConditionResult valuesMatch(ByteString attributeValue, |
| | | ByteString assertionValue) |
| | | public ConditionResult valuesMatch(ByteSequence attributeValue, |
| | | ByteSequence assertionValue) |
| | | { |
| | | if (areEqual(attributeValue, assertionValue)) |
| | | if (assertionValue.equals(attributeValue)) |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <T> T createIndexQuery(ByteString assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | public <T> T createIndexQuery(ByteSequence assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | { |
| | | //Normalize the assertion value. |
| | | ByteString normalValue = normalizeValue(assertionValue); |
| | | return factory.createExactMatchQuery( |
| | | indexer.getExtensibleIndexID(), |
| | | normalValue.value()); |
| | | // Normalize the assertion value. |
| | | return factory.createExactMatchQuery(indexer |
| | | .getExtensibleIndexID(), normalizeValue(assertionValue)); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Collation rule for Substring matching rule. |
| | | */ |
| | | private final class CollationSubstringMatchingRule |
| | | extends CollationMatchingRule |
| | | private final class CollationSubstringMatchingRule extends |
| | | CollationMatchingRule |
| | | { |
| | | //Substring Indexer associated with this instance. |
| | | // Substring Indexer associated with this instance. |
| | | private CollationSubstringExtensibleIndexer subIndexer; |
| | | |
| | | |
| | |
| | | /** |
| | | * Constructs a new CollationSubstringMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationSubstringMatchingRule(String nOID, |
| | | Collection<String> names,Locale locale) |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID,names,locale); |
| | | super(nOID, names, locale); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ByteString normalizeValue(ByteString value) |
| | | throws DirectoryException |
| | | public ByteString normalizeValue(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | CollationKey key = collator.getCollationKey(value.stringValue()); |
| | | return new ASN1OctetString(key.toByteArray()); |
| | | CollationKey key = collator.getCollationKey(value.toString()); |
| | | return ByteString.wrap(key.toByteArray()); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | private final class Assertion |
| | | { |
| | | //Initial part of the substring filter. |
| | | // Initial part of the substring filter. |
| | | private String subInitial; |
| | | |
| | | |
| | | //any parts of the substring filter. |
| | | // any parts of the substring filter. |
| | | private List<String> subAny; |
| | | |
| | | |
| | | //Final part of the substring filter. |
| | | // Final part of the substring filter. |
| | | private String subFinal; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of Assertion. |
| | | * @param subInitial Initial part of the filter. |
| | | * @param subAny Any part of the filter. |
| | | * @param subFinal Final part of the filter. |
| | | * |
| | | * @param subInitial |
| | | * Initial part of the filter. |
| | | * @param subAny |
| | | * Any part of the filter. |
| | | * @param subFinal |
| | | * Final part of the filter. |
| | | */ |
| | | Assertion(String subInitial, List<String> subAny, String subFinal) |
| | | private Assertion(String subInitial, List<String> subAny, |
| | | String subFinal) |
| | | { |
| | | this.subInitial = subInitial; |
| | | this.subAny = subAny; |
| | |
| | | |
| | | /** |
| | | * Returns the Initial part of the assertion. |
| | | * |
| | | * @return Initial part of assertion. |
| | | */ |
| | | private String getInitial() |
| | |
| | | |
| | | /** |
| | | * Returns the any part of the assertion. |
| | | * |
| | | * @return Any part of the assertion. |
| | | */ |
| | | private List<String> getAny() |
| | |
| | | |
| | | /** |
| | | * Returns the final part of the assertion. |
| | | * |
| | | * @return Final part of the assertion. |
| | | */ |
| | | private String getFinal() |
| | |
| | | |
| | | /** |
| | | * Parses the assertion from a given value. |
| | | * @param value The value that needs to be parsed. |
| | | * |
| | | * @param value |
| | | * The value that needs to be parsed. |
| | | * @return The parsed Assertion object containing the |
| | | * @throws org.opends.server.types.DirectoryException |
| | | */ |
| | | private Assertion parseAssertion(ByteString value) |
| | | throws DirectoryException |
| | | private Assertion parseAssertion(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | // Get a string representation of the value. |
| | | String filterString = value.stringValue(); |
| | | // Get a string representation of the value. |
| | | String filterString = value.toString(); |
| | | int endPos = filterString.length(); |
| | | |
| | | // Find the locations of all the asterisks in the value. Also, |
| | | // Find the locations of all the asterisks in the value. Also, |
| | | // check to see if there are any escaped values, since they will |
| | | // need special treatment. |
| | | boolean hasEscape = false; |
| | | LinkedList<Integer> asteriskPositions = new LinkedList<Integer>(); |
| | | for (int i=0; i < endPos; i++) |
| | | for (int i = 0; i < endPos; i++) |
| | | { |
| | | if (filterString.charAt(i) == 0x2A) // The asterisk. |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If there were no asterisks, then this isn't a substring filter. |
| | | if (asteriskPositions.isEmpty()) |
| | | { |
| | | Message message = ERR_SEARCH_FILTER_SUBSTRING_NO_ASTERISKS.get( |
| | | filterString, 0, endPos); |
| | | throw new DirectoryException( |
| | | ResultCode.PROTOCOL_ERROR, message); |
| | | Message message = |
| | | ERR_SEARCH_FILTER_SUBSTRING_NO_ASTERISKS.get(filterString, |
| | | 0, endPos); |
| | | throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); |
| | | } |
| | | |
| | | // If the value starts with an asterisk, then there is no |
| | | // subInitial component. Otherwise, parse out the subInitial. |
| | | // subInitial component. Otherwise, parse out the subInitial. |
| | | String subInitial; |
| | | int firstPos = asteriskPositions.removeFirst(); |
| | | if (firstPos == 0) |
| | |
| | | if (hasEscape) |
| | | { |
| | | CharBuffer buffer = CharBuffer.allocate(firstPos); |
| | | for (int i=0; i < firstPos; i++) |
| | | for (int i = 0; i < firstPos; i++) |
| | | { |
| | | if (filterString.charAt(i) == 0x5C) |
| | | { |
| | | char escapeValue = hexToEscapedChar(filterString, i +1); |
| | | i +=2; //Move to the next sequence. |
| | | char escapeValue = hexToEscapedChar(filterString, i + 1); |
| | | i += 2; // Move to the next sequence. |
| | | buffer.put(escapeValue); |
| | | } |
| | | else |
| | |
| | | } |
| | | else |
| | | { |
| | | subInitial = filterString.substring(0,firstPos); |
| | | subInitial = filterString.substring(0, firstPos); |
| | | } |
| | | } |
| | | |
| | | |
| | | // Next, process through the rest of the asterisks to get the |
| | | // subAny values. |
| | | List<String> subAny = new ArrayList<String>(); |
| | |
| | | if (hasEscape) |
| | | { |
| | | CharBuffer buffer = CharBuffer.allocate(length); |
| | | for (int i=firstPos+1; i < asteriskPos; i++) |
| | | for (int i = firstPos + 1; i < asteriskPos; i++) |
| | | { |
| | | if (filterString.charAt(i) == 0x5C) |
| | | { |
| | | char escapeValue = hexToEscapedChar(filterString, i + 1); |
| | | i +=2; //Move to the next sequence. |
| | | i += 2; // Move to the next sequence. |
| | | buffer.put(escapeValue); |
| | | } |
| | | else |
| | |
| | | } |
| | | else |
| | | { |
| | | subAny.add(filterString.substring(firstPos+1, firstPos+length+1)); |
| | | subAny.add(filterString.substring(firstPos + 1, firstPos |
| | | + length + 1)); |
| | | } |
| | | |
| | | |
| | | firstPos = asteriskPos; |
| | | } |
| | | |
| | | |
| | | // Finally, see if there is anything after the last asterisk, |
| | | // which would be the subFinal value. |
| | | String subFinal; |
| | | if (firstPos == (endPos-1)) |
| | | if (firstPos == (endPos - 1)) |
| | | { |
| | | subFinal = null; |
| | | } |
| | |
| | | if (hasEscape) |
| | | { |
| | | CharBuffer buffer = CharBuffer.allocate(length); |
| | | for (int i=firstPos+1; i < endPos; i++) |
| | | for (int i = firstPos + 1; i < endPos; i++) |
| | | { |
| | | if (filterString.charAt(i) == 0x5C) |
| | | { |
| | | char escapeValue = hexToEscapedChar(filterString, i + 1); |
| | | i +=2; //Move to the next sequence. |
| | | i += 2; // Move to the next sequence. |
| | | buffer.put(escapeValue); |
| | | } |
| | | else |
| | |
| | | } |
| | | else |
| | | { |
| | | subFinal = filterString.substring(firstPos+1, length + firstPos + 1); |
| | | subFinal = |
| | | filterString.substring(firstPos + 1, length + firstPos |
| | | + 1); |
| | | } |
| | | } |
| | | |
| | | return new Assertion(subInitial, subAny, subFinal); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ByteString normalizeAssertionValue(ByteString value) |
| | | throws DirectoryException { |
| | | public ByteString normalizeAssertionValue(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | Assertion assertion = parseAssertion(value); |
| | | String subInitial = assertion.getInitial(); |
| | | |
| | | // Normalize the Values in the following format: |
| | | // initialLength, initial, numberofany, anyLength1, any1, anyLength2, |
| | | // any2, ..., anyLengthn, anyn, finalLength, final |
| | | // initialLength, initial, numberofany, anyLength1, any1, |
| | | // anyLength2, any2, ..., anyLengthn, anyn, finalLength, |
| | | // final |
| | | CollationKey key = null; |
| | | List<Integer> normalizedList = new ArrayList<Integer>(); |
| | | |
| | | if(subInitial == null) |
| | | if (subInitial == null) |
| | | { |
| | | normalizedList.add(0); |
| | | } |
| | |
| | | { |
| | | key = collator.getCollationKey(subInitial); |
| | | byte[] initialBytes = key.toByteArray(); |
| | | // Last 4 bytes are 0s with PRIMARY strenght. |
| | | int length = initialBytes.length - 4 ; |
| | | |
| | | // Last 4 bytes are 0s with PRIMARY strength. |
| | | int length = initialBytes.length - 4; |
| | | normalizedList.add(length); |
| | | for(int i=0;i<length;i++) |
| | | for (int i = 0; i < length; i++) |
| | | { |
| | | normalizedList.add((int)initialBytes[i]); |
| | | normalizedList.add((int) initialBytes[i]); |
| | | } |
| | | } |
| | | |
| | | List<String> subAny = assertion.getAny(); |
| | | if (subAny.size() == 0) { |
| | | if (subAny.size() == 0) |
| | | { |
| | | normalizedList.add(0); |
| | | } |
| | | else |
| | | { |
| | | normalizedList.add(subAny.size()); |
| | | for(String any:subAny) |
| | | for (String any : subAny) |
| | | { |
| | | key = collator.getCollationKey(any); |
| | | byte[] anyBytes = key.toByteArray(); |
| | | int length = anyBytes.length - 4; |
| | | normalizedList.add(length); |
| | | for(int i=0;i<length;i++) |
| | | for (int i = 0; i < length; i++) |
| | | { |
| | | normalizedList.add((int)anyBytes[i]); |
| | | normalizedList.add((int) anyBytes[i]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | String subFinal = assertion.getFinal(); |
| | | if (subFinal == null) |
| | | { |
| | |
| | | byte[] subFinalBytes = key.toByteArray(); |
| | | int length = subFinalBytes.length - 4; |
| | | normalizedList.add(length); |
| | | for(int i=0;i<length;i++) |
| | | for (int i = 0; i < length; i++) |
| | | { |
| | | normalizedList.add((int)subFinalBytes[i]); |
| | | normalizedList.add((int) subFinalBytes[i]); |
| | | } |
| | | } |
| | | |
| | | byte[] normalizedBytes = new byte[normalizedList.size()]; |
| | | for(int i=0;i<normalizedList.size();i++) |
| | | for (int i = 0; i < normalizedList.size(); i++) |
| | | { |
| | | normalizedBytes[i] = normalizedList.get(i).byteValue(); |
| | | } |
| | | return new ASN1OctetString(normalizedBytes); |
| | | |
| | | return ByteString.wrap(normalizedBytes); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConditionResult valuesMatch(ByteString attributeValue, |
| | | ByteString assertionValue) |
| | | public ConditionResult valuesMatch(ByteSequence attributeValue, |
| | | ByteSequence assertionValue) |
| | | { |
| | | byte[] valueBytes = attributeValue.value(); |
| | | int valueLength = valueBytes.length - 4; |
| | | |
| | | byte[] assertionBytes = assertionValue.value(); |
| | | |
| | | int valueLength = attributeValue.length() - 4; |
| | | int valuePos = 0; // position in the value bytes array. |
| | | int assertPos = 0; // position in the assertion bytes array. |
| | | int subInitialLength = 0xFF & assertionBytes[0]; |
| | | //First byte is the length of subInitial. |
| | | |
| | | if(subInitialLength!= 0) |
| | | // First byte is the length of subInitial. |
| | | int subInitialLength = 0xFF & assertionValue.byteAt(0); |
| | | |
| | | if (subInitialLength != 0) |
| | | { |
| | | if(subInitialLength > valueLength) |
| | | if (subInitialLength > valueLength) |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | |
| | | for(;valuePos < subInitialLength; valuePos++) |
| | | for (; valuePos < subInitialLength; valuePos++) |
| | | { |
| | | if(valueBytes[valuePos]!=assertionBytes[valuePos+1]) |
| | | if (attributeValue.byteAt(valuePos) != assertionValue |
| | | .byteAt(valuePos + 1)) |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | } |
| | | } |
| | | |
| | | assertPos = subInitialLength + 1; |
| | | int anySize = 0xFF & assertionBytes[assertPos++]; |
| | | if(anySize!=0) |
| | | int anySize = 0xFF & assertionValue.byteAt(assertPos++); |
| | | if (anySize != 0) |
| | | { |
| | | while(anySize-- > 0) |
| | | while (anySize-- > 0) |
| | | { |
| | | int anyLength = 0xFF & assertionBytes[assertPos++]; |
| | | int anyLength = 0xFF & assertionValue.byteAt(assertPos++); |
| | | int end = valueLength - anyLength; |
| | | boolean match = false; |
| | | for(; valuePos <= end; valuePos++) |
| | | { |
| | | |
| | | if(assertionBytes[assertPos] == valueBytes[valuePos]) |
| | | for (; valuePos <= end; valuePos++) |
| | | { |
| | | if (assertionValue.byteAt(assertPos) == attributeValue |
| | | .byteAt(valuePos)) |
| | | { |
| | | boolean subMatch = true; |
| | | for(int i=1;i<anyLength;i++) |
| | | for (int i = 1; i < anyLength; i++) |
| | | { |
| | | |
| | | if(assertionBytes[assertPos+i] != valueBytes[valuePos+i]) |
| | | if (assertionValue.byteAt(assertPos + i) != attributeValue |
| | | .byteAt(valuePos + i)) |
| | | { |
| | | subMatch = false; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if(subMatch) |
| | | if (subMatch) |
| | | { |
| | | match = subMatch; |
| | | break; |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | if(match) |
| | | if (match) |
| | | { |
| | | valuePos += anyLength; |
| | | } |
| | |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | |
| | | assertPos = assertPos + anyLength; |
| | | } |
| | | } |
| | | |
| | | int finalLength = 0xFF & assertionBytes[assertPos++]; |
| | | if(finalLength!=0) |
| | | int finalLength = 0xFF & assertionValue.byteAt(assertPos++); |
| | | if (finalLength != 0) |
| | | { |
| | | if((valueLength - finalLength) < valuePos) |
| | | if ((valueLength - finalLength) < valuePos) |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | |
| | | valuePos = valueLength - finalLength; |
| | | |
| | | if(finalLength != assertionBytes.length - assertPos ) |
| | | if (finalLength != assertionValue.length() - assertPos) |
| | | { |
| | | //Some issue with the encoding. |
| | | // Some issue with the encoding. |
| | | return ConditionResult.FALSE; |
| | | } |
| | | |
| | | valuePos = valueLength - finalLength; |
| | | for (int i=0; i < finalLength; i++,valuePos++) |
| | | for (int i = 0; i < finalLength; i++, valuePos++) |
| | | { |
| | | if (assertionBytes[assertPos+i] != valueBytes[valuePos]) |
| | | if (assertionValue.byteAt(assertPos + i) != attributeValue |
| | | .byteAt(valuePos)) |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public final Collection<ExtensibleIndexer> getIndexers(IndexConfig config) |
| | | public final Collection<ExtensibleIndexer> getIndexers( |
| | | IndexConfig config) |
| | | { |
| | | Collection<ExtensibleIndexer> indexers = |
| | | new ArrayList<ExtensibleIndexer>(); |
| | | int substrLength = 6; //Default substring length; |
| | | if(subIndexer == null) |
| | | new ArrayList<ExtensibleIndexer>(); |
| | | int substrLength = 6; // Default substring length; |
| | | if (subIndexer == null) |
| | | { |
| | | if(config != null) |
| | | if (config != null) |
| | | { |
| | | substrLength = config.getSubstringLength(); |
| | | } |
| | | subIndexer = new CollationSubstringExtensibleIndexer(this, |
| | | substrLength); |
| | | subIndexer = |
| | | new CollationSubstringExtensibleIndexer(this, substrLength); |
| | | } |
| | | else |
| | | { |
| | | if(config !=null) |
| | | if (config != null) |
| | | { |
| | | if(config.getSubstringLength() !=subIndexer.gerSubstringLength()) |
| | | if (config.getSubstringLength() != subIndexer |
| | | .gerSubstringLength()) |
| | | { |
| | | subIndexer.setSubstringLength(substrLength); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if(indexer == null) |
| | | if (indexer == null) |
| | | { |
| | | indexer = new CollationSharedExtensibleIndexer(this); |
| | | } |
| | | |
| | | indexers.add(subIndexer); |
| | | indexers.add(indexer); |
| | | |
| | | return indexers; |
| | | } |
| | | |
| | |
| | | /** |
| | | * Decomposes an attribute value into a set of substring index keys. |
| | | * |
| | | * @param attValue Tthe normalized attribute value |
| | | * @param set A set into which the keys will be inserted. |
| | | * @param attValue |
| | | * The normalized attribute value |
| | | * @param set |
| | | * A set into which the keys will be inserted. |
| | | */ |
| | | private void subtringKeys(ByteString attValue, |
| | | Set<byte[]> keys) |
| | | private void subtringKeys(ByteString attValue, Set<byte[]> keys) |
| | | { |
| | | String value = attValue.stringValue(); |
| | | String value = attValue.toString(); |
| | | int keyLength = subIndexer.gerSubstringLength(); |
| | | for (int i = 0, remain = value.length(); remain > 0; i++, remain--) |
| | | { |
| | |
| | | /** |
| | | * Decomposes an attribute value into a set of substring index keys. |
| | | * |
| | | * @param value The normalized attribute value |
| | | * @param modifiedKeys The map into which the modified |
| | | * keys will be inserted. |
| | | * @param insert <code>true</code> if generated keys should |
| | | * be inserted or <code>false</code> otherwise. |
| | | * @param value |
| | | * The normalized attribute value |
| | | * @param modifiedKeys |
| | | * The map into which the modified keys will be inserted. |
| | | * @param insert |
| | | * <code>true</code> if generated keys should be inserted |
| | | * or <code>false</code> otherwise. |
| | | */ |
| | | private void substringKeys(ByteString attValue, |
| | | Map<byte[], Boolean> modifiedKeys, |
| | | Boolean insert) |
| | | Map<byte[], Boolean> modifiedKeys, Boolean insert) |
| | | { |
| | | String value = attValue.stringValue(); |
| | | String value = attValue.toString(); |
| | | int keyLength = subIndexer.gerSubstringLength(); |
| | | for (int i = 0, remain = value.length(); remain > 0; i++, remain--) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Makes a byte array representing a substring index key for |
| | | * one substring of a value. |
| | | * Makes a byte array representing a substring index key for one |
| | | * substring of a value. |
| | | * |
| | | * @param value The String containing the value. |
| | | * @param pos The starting position of the substring. |
| | | * @param len The length of the substring. |
| | | * @param value |
| | | * The String containing the value. |
| | | * @param pos |
| | | * The starting position of the substring. |
| | | * @param len |
| | | * The length of the substring. |
| | | * @return A byte array containing a substring key. |
| | | */ |
| | | private byte[] makeSubstringKey(String value, int pos, int len) |
| | |
| | | |
| | | |
| | | /** |
| | | * Uses an equality index to retrieve the entry IDs that might contain a |
| | | * given initial substring. |
| | | * @param bytes A normalized initial substring of an attribute value. |
| | | * Uses an equality index to retrieve the entry IDs that might |
| | | * contain a given initial substring. |
| | | * |
| | | * @param bytes |
| | | * A normalized initial substring of an attribute value. |
| | | * @return The candidate entry IDs. |
| | | */ |
| | | private <T> T matchInitialSubstring(String value, |
| | | IndexQueryFactory<T> factory) |
| | | IndexQueryFactory<T> factory) |
| | | { |
| | | byte[] lower = makeSubstringKey(value, 0, value.length()); |
| | | byte[] upper = new byte[lower.length]; |
| | |
| | | break; |
| | | } |
| | | } |
| | | //Use the shared equality indexer. |
| | | return factory.createRangeMatchQuery( |
| | | indexer.getExtensibleIndexID(), |
| | | lower, |
| | | upper, |
| | | true, |
| | | false); |
| | | // Use the shared equality indexer. |
| | | return factory.createRangeMatchQuery(indexer |
| | | .getExtensibleIndexID(), ByteString.wrap(lower), ByteString |
| | | .wrap(upper), true, false); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the Index Records that might contain a given substring. |
| | | * @param value A String representing the attribute value. |
| | | * @param factory An IndexQueryFactory which issues calls to the backend. |
| | | * @param substrLength The length of the substring. |
| | | * |
| | | * @param value |
| | | * A String representing the attribute value. |
| | | * @param factory |
| | | * An IndexQueryFactory which issues calls to the backend. |
| | | * @param substrLength |
| | | * The length of the substring. |
| | | * @return The candidate entry IDs. |
| | | */ |
| | | private <T> T matchSubstring(String value, |
| | | IndexQueryFactory<T> factory) |
| | | IndexQueryFactory<T> factory) |
| | | { |
| | | T intersectionQuery = null; |
| | | int substrLength = subIndexer.gerSubstringLength(); |
| | |
| | | { |
| | | if (upper[i] == 0xFF) |
| | | { |
| | | // We have to carry the overflow to the more significant byte. |
| | | // We have to carry the overflow to the more significant |
| | | // byte. |
| | | upper[i] = 0; |
| | | } else |
| | | } |
| | | else |
| | | { |
| | | // No overflow, we can stop. |
| | | upper[i] = (byte) (upper[i] + 1); |
| | |
| | | } |
| | | // Read the range: lower <= keys < upper. |
| | | intersectionQuery = |
| | | factory.createRangeMatchQuery( |
| | | subIndexer.getExtensibleIndexID(), |
| | | lower, |
| | | upper, |
| | | true, |
| | | false); |
| | | factory.createRangeMatchQuery(subIndexer |
| | | .getExtensibleIndexID(), ByteString.wrap(lower), |
| | | ByteString.wrap(upper), true, false); |
| | | } |
| | | else |
| | | { |
| | | List<T> queryList = new ArrayList<T>(); |
| | | Set<byte[]> set = |
| | | new TreeSet<byte[]>(new AttributeIndex.KeyComparator()); |
| | | new TreeSet<byte[]>(new AttributeIndex.KeyComparator()); |
| | | for (int first = 0, last = substrLength; |
| | | last <= value.length(); first++, last++) |
| | | last <= value.length(); |
| | | first++, last++) |
| | | { |
| | | byte[] keyBytes; |
| | | keyBytes = makeSubstringKey(value, first, substrLength); |
| | |
| | | |
| | | for (byte[] keyBytes : set) |
| | | { |
| | | T single = factory.createExactMatchQuery( |
| | | subIndexer.getExtensibleIndexID(), |
| | | keyBytes); |
| | | T single = |
| | | factory.createExactMatchQuery(subIndexer |
| | | .getExtensibleIndexID(), ByteString.wrap(keyBytes)); |
| | | queryList.add(single); |
| | | } |
| | | intersectionQuery = |
| | | factory.createIntersectionQuery(queryList); |
| | | intersectionQuery = factory.createIntersectionQuery(queryList); |
| | | } |
| | | return intersectionQuery; |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <T> T createIndexQuery(ByteString assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | public <T> T createIndexQuery(ByteSequence assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | { |
| | | Assertion assertion = parseAssertion(assertionValue); |
| | | String subInitial = assertion.getInitial(); |
| | |
| | | |
| | | if (subInitial == null && subAny.size() == 0 && subFinal == null) |
| | | { |
| | | //Can happen with a filter like "cn:en.6:=*". |
| | | //Just return an empty record. |
| | | // Can happen with a filter like "cn:en.6:=*". |
| | | // Just return an empty record. |
| | | return factory.createMatchAllQuery(); |
| | | } |
| | | List<String> elements = new ArrayList<String>(); |
| | | if (subInitial != null) |
| | | { |
| | | //Always use the shared indexer for initial match. |
| | | // Always use the shared indexer for initial match. |
| | | T query = matchInitialSubstring(subInitial, factory); |
| | | queries.add(query); |
| | | } |
| | |
| | | elements.add(subFinal); |
| | | } |
| | | |
| | | |
| | | for (String element : elements) |
| | | { |
| | | queries.add(matchSubstring(element, factory)); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | *An abstract Collation rule for Ordering matching rule. |
| | | * An abstract Collation rule for Ordering matching rule. |
| | | */ |
| | | private abstract class CollationOrderingMatchingRule |
| | | extends CollationMatchingRule |
| | | private abstract class CollationOrderingMatchingRule extends |
| | | CollationMatchingRule |
| | | { |
| | | /** |
| | | * Constructs a new CollationOrderingMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationOrderingMatchingRule(String nOID, |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID,names,locale); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ByteString normalizeValue(ByteString value) |
| | | throws DirectoryException |
| | | { |
| | | CollationKey key = collator.getCollationKey(value.stringValue()); |
| | | return new ASN1OctetString(key.toByteArray()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Compares the first value to the second and returns a value that |
| | | * indicates their relative order. |
| | | * |
| | | * @param b1 The normalized form of the first value to |
| | | * compare. |
| | | * @param b2 The normalized form of the second value to |
| | | * compare. |
| | | * |
| | | * @return A negative integer if {@code value1} should come before |
| | | * {@code value2} in ascending order, a positive integer if |
| | | * {@code value1} should come after {@code value2} in |
| | | * ascending order, or zero if there is no difference |
| | | * between the values with regard to ordering. |
| | | */ |
| | | protected int compare(byte[] b1, byte[] b2) { |
| | | //Compare values using byte arrays. |
| | | int minLength = Math.min(b1.length, b2.length); |
| | | |
| | | for (int i=0; i < minLength; i++) |
| | | { |
| | | int firstByte = 0xFF & ((int)b1[i]); |
| | | int secondByte = 0xFF & ((int)b2[i]); |
| | | |
| | | if (firstByte == secondByte) |
| | | { |
| | | continue; |
| | | } |
| | | else if (firstByte < secondByte) |
| | | { |
| | | return -1; |
| | | } |
| | | else if (firstByte > secondByte) |
| | | { |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | if (b1.length == b2.length) |
| | | { |
| | | return 0; |
| | | } |
| | | else if (b1.length < b2.length) |
| | | { |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | return 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Collation matching rule for Less-than matching rule. |
| | | */ |
| | | private final class CollationLessThanMatchingRule |
| | | extends CollationOrderingMatchingRule |
| | | { |
| | | |
| | | /** |
| | | * Constructs a new CollationLessThanMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | */ |
| | | private CollationLessThanMatchingRule(String nOID, |
| | | Collection<String> names, Locale locale) |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID, names, locale); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ByteString normalizeValue(ByteSequence value) |
| | | throws DirectoryException |
| | | { |
| | | CollationKey key = collator.getCollationKey(value.toString()); |
| | | return ByteString.wrap(key.toByteArray()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Collation matching rule for Less-than matching rule. |
| | | */ |
| | | private final class CollationLessThanMatchingRule extends |
| | | CollationOrderingMatchingRule |
| | | { |
| | | |
| | | /** |
| | | * Constructs a new CollationLessThanMatchingRule. |
| | | * |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationLessThanMatchingRule(String nOID, |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID, names, locale); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConditionResult valuesMatch(ByteString attributeValue, |
| | | ByteString assertionValue) |
| | | public ConditionResult valuesMatch(ByteSequence attributeValue, |
| | | ByteSequence assertionValue) |
| | | { |
| | | int ret = compare(attributeValue.value(), assertionValue.value()); |
| | | int ret = attributeValue.compareTo(assertionValue); |
| | | |
| | | if (ret < 0) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <T> T createIndexQuery(ByteString assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | public <T> T createIndexQuery(ByteSequence assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | { |
| | | byte[] lower = new byte[0]; |
| | | byte[] upper = normalizeValue(assertionValue).value(); |
| | | return factory.createRangeMatchQuery(indexer.getExtensibleIndexID(), |
| | | lower, |
| | | upper, |
| | | false, |
| | | false); |
| | | return factory.createRangeMatchQuery(indexer |
| | | .getExtensibleIndexID(), ByteString.empty(), |
| | | normalizeValue(assertionValue), false, false); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Collation rule for less-than-equal-to matching rule. |
| | | */ |
| | | private final class CollationLessThanOrEqualToMatchingRule |
| | | extends CollationOrderingMatchingRule |
| | | private final class CollationLessThanOrEqualToMatchingRule extends |
| | | CollationOrderingMatchingRule |
| | | { |
| | | |
| | | /** |
| | | * Constructs a new CollationLessThanOrEqualToMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationLessThanOrEqualToMatchingRule(String nOID, |
| | | Collection<String> names, |
| | | Locale locale) |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID, names, locale); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConditionResult valuesMatch(ByteString attributeValue, |
| | | ByteString assertionValue) |
| | | public ConditionResult valuesMatch(ByteSequence attributeValue, |
| | | ByteSequence assertionValue) |
| | | { |
| | | int ret = compare(attributeValue.value(), assertionValue.value()); |
| | | int ret = attributeValue.compareTo(assertionValue); |
| | | |
| | | if (ret <= 0) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <T> T createIndexQuery(ByteString assertionValue, |
| | | IndexQueryFactory<T> factory) |
| | | throws DirectoryException |
| | | public <T> T createIndexQuery(ByteSequence assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | { |
| | | byte[] lower = new byte[0]; |
| | | byte[] upper = normalizeValue(assertionValue).value(); |
| | | // Read the range: lower < keys <= upper. |
| | | return factory.createRangeMatchQuery(indexer.getExtensibleIndexID(), |
| | | lower, |
| | | upper, |
| | | false, |
| | | true); |
| | | return factory.createRangeMatchQuery(indexer |
| | | .getExtensibleIndexID(), ByteString.empty(), |
| | | normalizeValue(assertionValue), false, true); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Collation rule for greater-than matching rule. |
| | | */ |
| | | private final class CollationGreaterThanMatchingRule |
| | | extends CollationOrderingMatchingRule |
| | | private final class CollationGreaterThanMatchingRule extends |
| | | CollationOrderingMatchingRule |
| | | { |
| | | |
| | | /** |
| | | * Constructs a new CollationGreaterThanMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationGreaterThanMatchingRule(String nOID, |
| | | Collection<String> names, Locale locale) |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID, names, locale); |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConditionResult valuesMatch(ByteString attributeValue, |
| | | ByteString assertionValue) |
| | | public ConditionResult valuesMatch(ByteSequence attributeValue, |
| | | ByteSequence assertionValue) |
| | | { |
| | | int ret = compare(attributeValue.value(), assertionValue.value()); |
| | | int ret = attributeValue.compareTo(assertionValue); |
| | | |
| | | if (ret > 0) { |
| | | if (ret > 0) |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } else { |
| | | } |
| | | else |
| | | { |
| | | return ConditionResult.FALSE; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <T> T createIndexQuery(ByteString assertionValue, |
| | | IndexQueryFactory<T> factory) |
| | | throws DirectoryException |
| | | public <T> T createIndexQuery(ByteSequence assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | { |
| | | byte[] lower = normalizeValue(assertionValue).value(); |
| | | byte[] upper = new byte[0]; |
| | | return factory.createRangeMatchQuery(indexer.getExtensibleIndexID(), |
| | | lower, |
| | | upper, |
| | | false, |
| | | false); |
| | | return factory.createRangeMatchQuery(indexer |
| | | .getExtensibleIndexID(), normalizeValue(assertionValue), |
| | | ByteString.empty(), false, false); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Collation rule for greater-than-equal-to matching rule. |
| | | */ |
| | | private final class CollationGreaterThanOrEqualToMatchingRule |
| | | extends CollationOrderingMatchingRule |
| | | private final class CollationGreaterThanOrEqualToMatchingRule extends |
| | | CollationOrderingMatchingRule |
| | | { |
| | | |
| | | /** |
| | | * Constructs a new CollationGreaterThanOrEqualToMatchingRule. |
| | | * |
| | | * @param nOID OID of the collation matching rule |
| | | * @param names names of this matching rule |
| | | * @param locale Locale of the collation matching rule |
| | | * @param nOID |
| | | * OID of the collation matching rule |
| | | * @param names |
| | | * names of this matching rule |
| | | * @param locale |
| | | * Locale of the collation matching rule |
| | | */ |
| | | private CollationGreaterThanOrEqualToMatchingRule(String nOID, |
| | | Collection<String> names, |
| | | Locale locale) |
| | | Collection<String> names, Locale locale) |
| | | { |
| | | super(nOID, names, locale); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConditionResult valuesMatch(ByteString attributeValue, |
| | | ByteString assertionValue) |
| | | public ConditionResult valuesMatch(ByteSequence attributeValue, |
| | | ByteSequence assertionValue) |
| | | { |
| | | int ret = compare(attributeValue.value(),assertionValue.value()); |
| | | int ret = attributeValue.compareTo(assertionValue); |
| | | |
| | | if (ret >= 0) |
| | | { |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public <T> T createIndexQuery(ByteString assertionValue, |
| | | IndexQueryFactory<T> factory) |
| | | throws DirectoryException |
| | | public <T> T createIndexQuery(ByteSequence assertionValue, |
| | | IndexQueryFactory<T> factory) throws DirectoryException |
| | | { |
| | | byte[] lower = normalizeValue(assertionValue).value(); |
| | | byte[] upper = new byte[0]; |
| | | // Read the range: lower <= keys < upper. |
| | | return factory.createRangeMatchQuery(indexer.getExtensibleIndexID(), |
| | | lower, |
| | | upper, |
| | | true, |
| | | false); |
| | | return factory.createRangeMatchQuery(indexer |
| | | .getExtensibleIndexID(), normalizeValue(assertionValue), |
| | | ByteString.empty(), true, false); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Extensible Indexer class for Collation Matching rules which share the |
| | | * same index. This Indexer is shared by Equality and Ordering Collation |
| | | * Matching Rules. |
| | | * Extensible Indexer class for Collation Matching rules which share |
| | | * the same index. This Indexer is shared by Equality and Ordering |
| | | * Collation Matching Rules. |
| | | */ |
| | | private final class CollationSharedExtensibleIndexer |
| | | extends ExtensibleIndexer |
| | | private final class CollationSharedExtensibleIndexer extends |
| | | ExtensibleIndexer |
| | | { |
| | | |
| | | /** |
| | |
| | | /** |
| | | * Creates a new instance of CollationSharedExtensibleIndexer. |
| | | * |
| | | * @param matchingRule The Collation Matching Rule. |
| | | * @param matchingRule |
| | | * The Collation Matching Rule. |
| | | */ |
| | | private CollationSharedExtensibleIndexer( |
| | | CollationMatchingRule matchingRule) |
| | | CollationMatchingRule matchingRule) |
| | | { |
| | | this.matchingRule = matchingRule; |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public final void getKeys(AttributeValue value, |
| | | Set<byte[]> keys) |
| | | public final void getKeys(AttributeValue value, Set<byte[]> keys) |
| | | { |
| | | ByteString key; |
| | | try |
| | | { |
| | | key = matchingRule.normalizeValue(value.getValue()); |
| | | keys.add(key.value()); |
| | | keys.add(key.toByteArray()); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | |
| | | */ |
| | | @Override |
| | | public final void getKeys(AttributeValue value, |
| | | Map<byte[], Boolean> modifiedKeys, |
| | | Boolean insert) |
| | | Map<byte[], Boolean> modifiedKeys, Boolean insert) |
| | | { |
| | | Set<byte[]> keys = new HashSet<byte[]>(); |
| | | getKeys(value, keys); |
| | |
| | | |
| | | /** |
| | | * Extensible Indexer class for Collation Substring Matching rules. |
| | | * This Indexer is used by Substring Collation Matching Rules. |
| | | * This Indexer is used by Substring Collation Matching Rules. |
| | | */ |
| | | private final class CollationSubstringExtensibleIndexer |
| | | extends ExtensibleIndexer |
| | | private final class CollationSubstringExtensibleIndexer extends |
| | | ExtensibleIndexer |
| | | { |
| | | //The CollationSubstringMatching Rule. |
| | | // The CollationSubstringMatching Rule. |
| | | private final CollationSubstringMatchingRule matchingRule; |
| | | |
| | | |
| | | |
| | | //The substring length. |
| | | // The substring length. |
| | | private int substringLen; |
| | | |
| | | |
| | |
| | | /** |
| | | * Creates a new instance of CollationSubstringExtensibleIndexer. |
| | | * |
| | | * @param matchingRule The CollationSubstringMatching Rule. |
| | | * @param substringLen The substring length. |
| | | * @param matchingRule |
| | | * The CollationSubstringMatching Rule. |
| | | * @param substringLen |
| | | * The substring length. |
| | | */ |
| | | private CollationSubstringExtensibleIndexer( |
| | | CollationSubstringMatchingRule matchingRule, |
| | | int substringLen) |
| | | CollationSubstringMatchingRule matchingRule, int substringLen) |
| | | { |
| | | this.matchingRule = matchingRule; |
| | | this.substringLen = substringLen; |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void getKeys(AttributeValue value, |
| | | Set<byte[]> keys) |
| | | public void getKeys(AttributeValue value, Set<byte[]> keys) |
| | | { |
| | | matchingRule.subtringKeys(value.getValue(), |
| | | keys); |
| | | matchingRule.subtringKeys(value.getValue(), keys); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public void getKeys(AttributeValue attValue, |
| | | Map<byte[], Boolean> modifiedKeys, |
| | | Boolean insert) |
| | | Map<byte[], Boolean> modifiedKeys, Boolean insert) |
| | | { |
| | | matchingRule.substringKeys(attValue.getValue(), |
| | | modifiedKeys, |
| | | insert); |
| | | matchingRule.substringKeys(attValue.getValue(), modifiedKeys, |
| | | insert); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | /** |
| | | * Returns the substring length. |
| | | * |
| | | * @return The length of the substring. |
| | | */ |
| | | private int gerSubstringLength() |
| | |
| | | |
| | | /** |
| | | * Sets the substring length. |
| | | * @param substringLen The substring length. |
| | | * |
| | | * @param substringLen |
| | | * The substring length. |
| | | */ |
| | | private void setSubstringLength(int substringLen) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * A utility class for extracting the OID and Language Tag from the |
| | | * configuration entry. |
| | | */ |
| | | private final class CollationMapper |
| | | { |
| | | //OID of the collation rule. |
| | | private String oid; |
| | | // OID of the collation rule. |
| | | private String oid; |
| | | |
| | | //Language Tag. |
| | | private String lTag; |
| | | // Language Tag. |
| | | private String lTag; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of CollationMapper. |
| | | * |
| | | * @param collation The collation text in the LOCALE:OID format. |
| | | * @param collation |
| | | * The collation text in the LOCALE:OID format. |
| | | */ |
| | | private CollationMapper(String collation) |
| | | { |
| | | int index = collation.indexOf(":"); |
| | | if(index>0) |
| | | if (index > 0) |
| | | { |
| | | oid = collation.substring(index+1,collation.length()); |
| | | lTag = collation.substring(0,index); |
| | | oid = collation.substring(index + 1, collation.length()); |
| | | lTag = collation.substring(0, index); |
| | | } |
| | | } |
| | | |
| | |
| | | return lTag; |
| | | } |
| | | } |
| | | } |
| | | } |