001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.controls;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.ArrayList;
033 import java.util.List;
034
035 import org.opends.server.api.ApproximateMatchingRule;
036 import org.opends.server.api.EqualityMatchingRule;
037 import org.opends.server.api.MatchingRule;
038 import org.opends.server.api.OrderingMatchingRule;
039 import org.opends.server.api.SubstringMatchingRule;
040 import org.opends.server.core.DirectoryServer;
041 import org.opends.server.protocols.asn1.ASN1Element;
042 import org.opends.server.protocols.asn1.ASN1OctetString;
043 import org.opends.server.protocols.asn1.ASN1Sequence;
044 import org.opends.server.protocols.ldap.LDAPResultCode;
045 import org.opends.server.types.AttributeType;
046 import org.opends.server.types.AttributeValue;
047 import org.opends.server.types.ByteString;
048 import org.opends.server.types.ConditionResult;
049 import org.opends.server.types.LDAPException;
050 import org.opends.server.types.RawFilter;
051 import org.opends.server.util.Validator;
052
053 import static org.opends.server.loggers.debug.DebugLogger.*;
054 import org.opends.server.loggers.debug.DebugTracer;
055 import org.opends.server.types.DebugLogLevel;
056 import static org.opends.messages.ProtocolMessages.*;
057 import static org.opends.server.protocols.ldap.LDAPConstants.*;
058 import static org.opends.server.util.StaticUtils.*;
059
060
061
062 /**
063 * This class defines a filter that may be used in conjunction with the matched
064 * values control to indicate which particular values of a multivalued attribute
065 * should be returned. The matched values filter is essentially a subset of an
066 * LDAP search filter, lacking support for AND, OR, and NOT components, and
067 * lacking support for the dnAttributes component of extensible matching
068 * filters.
069 */
070 public class MatchedValuesFilter
071 {
072 /**
073 * The tracer object for the debug logger.
074 */
075 private static final DebugTracer TRACER = getTracer();
076
077
078
079
080 /**
081 * The BER type associated with the equalityMatch filter type.
082 */
083 public static final byte EQUALITY_MATCH_TYPE = (byte) 0xA3;
084
085
086
087 /**
088 * The BER type associated with the substrings filter type.
089 */
090 public static final byte SUBSTRINGS_TYPE = (byte) 0xA4;
091
092
093
094 /**
095 * The BER type associated with the greaterOrEqual filter type.
096 */
097 public static final byte GREATER_OR_EQUAL_TYPE = (byte) 0xA5;
098
099
100
101 /**
102 * The BER type associated with the lessOrEqual filter type.
103 */
104 public static final byte LESS_OR_EQUAL_TYPE = (byte) 0xA6;
105
106
107
108 /**
109 * The BER type associated with the present filter type.
110 */
111 public static final byte PRESENT_TYPE = (byte) 0x87;
112
113
114
115 /**
116 * The BER type associated with the approxMatch filter type.
117 */
118 public static final byte APPROXIMATE_MATCH_TYPE = (byte) 0xA8;
119
120
121
122 /**
123 * The BER type associated with the extensibleMatch filter type.
124 */
125 public static final byte EXTENSIBLE_MATCH_TYPE = (byte) 0xA9;
126
127
128
129 // The approximate matching rule for this matched values filter.
130 private ApproximateMatchingRule approximateMatchingRule;
131
132 // The normalized subFinal value for this matched values filter.
133 private ASN1OctetString normalizedSubFinal;
134
135 // The normalized subInitial value for this matched values filter.
136 private ASN1OctetString normalizedSubInitial;
137
138 // The raw, unprocessed assertion value for this matched values filter.
139 private ByteString rawAssertionValue;
140
141 // The subFinal value for this matched values filter.
142 private ByteString subFinal;
143
144 // The subInitial value for this matched values filter.
145 private ByteString subInitial;
146
147 // The processed attribute type for this matched values filter.
148 private AttributeType attributeType;
149
150 // The processed assertion value for this matched values filter.
151 private AttributeValue assertionValue;
152
153 // Indicates whether the elements of this matched values filter have been
154 // fully decoded.
155 private boolean decoded;
156
157 // The match type for this matched values filter.
158 private byte matchType;
159
160 // The equality matching rule for this matched values filter.
161 private EqualityMatchingRule equalityMatchingRule;
162
163 // The set of normalized subAny values for this matched values filter.
164 private List<ASN1OctetString> normalizedSubAny;
165
166 // The set of subAny values for this matched values filter.
167 private List<ByteString> subAny;
168
169 // The matching rule for this matched values filter.
170 private MatchingRule matchingRule;
171
172 // The ordering matching rule for this matched values filter.
173 private OrderingMatchingRule orderingMatchingRule;
174
175 // The matching rule ID for this matched values filter.
176 private String matchingRuleID;
177
178 // The raw, unprocessed attribute type for this matched values filter.
179 private String rawAttributeType;
180
181 // The substring matching rule for this matched values filter.
182 private SubstringMatchingRule substringMatchingRule;
183
184
185
186 /**
187 * Creates a new matched values filter with the provided information.
188 *
189 * @param matchType The match type for this matched values filter.
190 * @param rawAttributeType The raw, unprocessed attribute type.
191 * @param rawAssertionValue The raw, unprocessed assertion value.
192 * @param subInitial The subInitial element.
193 * @param subAny The set of subAny elements.
194 * @param subFinal The subFinal element.
195 * @param matchingRuleID The matching rule ID.
196 */
197 private MatchedValuesFilter(byte matchType, String rawAttributeType,
198 ByteString rawAssertionValue,
199 ByteString subInitial, List<ByteString> subAny,
200 ByteString subFinal, String matchingRuleID)
201 {
202 this.matchType = matchType;
203 this.rawAttributeType = rawAttributeType;
204 this.rawAssertionValue = rawAssertionValue;
205 this.subInitial = subInitial;
206 this.subAny = subAny;
207 this.subFinal = subFinal;
208 this.matchingRuleID = matchingRuleID;
209
210 decoded = false;
211 attributeType = null;
212 assertionValue = null;
213 matchingRule = null;
214 normalizedSubInitial = null;
215 normalizedSubAny = null;
216 normalizedSubFinal = null;
217 approximateMatchingRule = null;
218 equalityMatchingRule = null;
219 orderingMatchingRule = null;
220 substringMatchingRule = null;
221 }
222
223
224
225 /**
226 * Creates a new equalityMatch filter with the provided information.
227 *
228 * @param rawAttributeType The raw, unprocessed attribute type.
229 * @param rawAssertionValue The raw, unprocessed assertion value.
230 *
231 * @return The created equalityMatch filter.
232 */
233 public static MatchedValuesFilter createEqualityFilter(
234 String rawAttributeType,
235 ByteString rawAssertionValue)
236 {
237 Validator.ensureNotNull(rawAttributeType,rawAssertionValue);
238
239 return new MatchedValuesFilter(EQUALITY_MATCH_TYPE, rawAttributeType,
240 rawAssertionValue, null, null, null, null);
241 }
242
243
244
245 /**
246 * Creates a new equalityMatch filter with the provided information.
247 *
248 * @param attributeType The attribute type.
249 * @param assertionValue The assertion value.
250 *
251 * @return The created equalityMatch filter.
252 */
253 public static MatchedValuesFilter createEqualityFilter(
254 AttributeType attributeType,
255 AttributeValue assertionValue)
256 {
257 Validator.ensureNotNull(attributeType, assertionValue);
258 String rawAttributeType = attributeType.getNameOrOID();
259 ASN1OctetString rawAssertionValue = assertionValue.getValue()
260 .toASN1OctetString();
261
262 MatchedValuesFilter filter =
263 new MatchedValuesFilter(EQUALITY_MATCH_TYPE, rawAttributeType,
264 rawAssertionValue, null, null, null, null);
265 filter.attributeType = attributeType;
266 filter.assertionValue = assertionValue;
267
268 return filter;
269 }
270
271
272
273 /**
274 * Creates a new substrings filter with the provided information.
275 *
276 * @param rawAttributeType The raw, unprocessed attribute type.
277 * @param subInitial The subInitial element.
278 * @param subAny The set of subAny elements.
279 * @param subFinal The subFinal element.
280 *
281 * @return The created substrings filter.
282 */
283 public static MatchedValuesFilter createSubstringsFilter(
284 String rawAttributeType,
285 ByteString subInitial,
286 List<ByteString> subAny,
287 ByteString subFinal)
288 {
289 Validator.ensureNotNull(rawAttributeType);
290 return new MatchedValuesFilter(SUBSTRINGS_TYPE, rawAttributeType, null,
291 subInitial, subAny, subFinal, null);
292 }
293
294
295
296 /**
297 * Creates a new substrings filter with the provided information.
298 *
299 * @param attributeType The raw, unprocessed attribute type.
300 * @param subInitial The subInitial element.
301 * @param subAny The set of subAny elements.
302 * @param subFinal The subFinal element.
303 *
304 * @return The created substrings filter.
305 */
306 public static MatchedValuesFilter createSubstringsFilter(
307 AttributeType attributeType,
308 ByteString subInitial,
309 List<ByteString> subAny,
310 ByteString subFinal)
311 {
312 Validator.ensureNotNull(attributeType);
313 String rawAttributeType = attributeType.getNameOrOID();
314
315 MatchedValuesFilter filter =
316 new MatchedValuesFilter(SUBSTRINGS_TYPE, rawAttributeType, null,
317 subInitial, subAny, subFinal, null);
318 filter.attributeType = attributeType;
319
320 return filter;
321 }
322
323
324
325 /**
326 * Creates a new greaterOrEqual filter with the provided information.
327 *
328 * @param rawAttributeType The raw, unprocessed attribute type.
329 * @param rawAssertionValue The raw, unprocessed assertion value.
330 *
331 * @return The created greaterOrEqual filter.
332 */
333 public static MatchedValuesFilter createGreaterOrEqualFilter(
334 String rawAttributeType,
335 ByteString rawAssertionValue)
336 {
337 Validator.ensureNotNull(rawAttributeType, rawAssertionValue);
338
339 return new MatchedValuesFilter(GREATER_OR_EQUAL_TYPE, rawAttributeType,
340 rawAssertionValue, null, null, null, null);
341 }
342
343
344
345 /**
346 * Creates a new greaterOrEqual filter with the provided information.
347 *
348 * @param attributeType The attribute type.
349 * @param assertionValue The assertion value.
350 *
351 * @return The created greaterOrEqual filter.
352 */
353 public static MatchedValuesFilter createGreaterOrEqualFilter(
354 AttributeType attributeType,
355 AttributeValue assertionValue)
356 {
357 Validator.ensureNotNull(attributeType, assertionValue);
358
359 String rawAttributeType = attributeType.getNameOrOID();
360 ASN1OctetString rawAssertionValue =
361 assertionValue.getValue().toASN1OctetString();
362
363 MatchedValuesFilter filter =
364 new MatchedValuesFilter(GREATER_OR_EQUAL_TYPE, rawAttributeType,
365 rawAssertionValue, null, null, null, null);
366 filter.attributeType = attributeType;
367 filter.assertionValue = assertionValue;
368
369 return filter;
370 }
371
372
373
374 /**
375 * Creates a new lessOrEqual filter with the provided information.
376 *
377 * @param rawAttributeType The raw, unprocessed attribute type.
378 * @param rawAssertionValue The raw, unprocessed assertion value.
379 *
380 * @return The created lessOrEqual filter.
381 */
382 public static MatchedValuesFilter createLessOrEqualFilter(
383 String rawAttributeType,
384 ByteString rawAssertionValue)
385 {
386 Validator.ensureNotNull(rawAttributeType, rawAssertionValue);
387 return new MatchedValuesFilter(LESS_OR_EQUAL_TYPE, rawAttributeType,
388 rawAssertionValue, null, null, null, null);
389 }
390
391
392
393 /**
394 * Creates a new lessOrEqual filter with the provided information.
395 *
396 * @param attributeType The attribute type.
397 * @param assertionValue The assertion value.
398 *
399 * @return The created lessOrEqual filter.
400 */
401 public static MatchedValuesFilter createLessOrEqualFilter(
402 AttributeType attributeType,
403 AttributeValue assertionValue)
404 {
405 Validator.ensureNotNull(attributeType, assertionValue);
406
407 String rawAttributeType = attributeType.getNameOrOID();
408 ASN1OctetString rawAssertionValue =
409 assertionValue.getValue().toASN1OctetString();
410
411 MatchedValuesFilter filter =
412 new MatchedValuesFilter(LESS_OR_EQUAL_TYPE, rawAttributeType,
413 rawAssertionValue, null, null, null, null);
414 filter.attributeType = attributeType;
415 filter.assertionValue = assertionValue;
416
417 return filter;
418 }
419
420
421
422 /**
423 * Creates a new present filter with the provided information.
424 *
425 * @param rawAttributeType The raw, unprocessed attribute type.
426 *
427 * @return The created present filter.
428 */
429 public static MatchedValuesFilter createPresentFilter(String rawAttributeType)
430 {
431 Validator.ensureNotNull(rawAttributeType) ;
432 return new MatchedValuesFilter(PRESENT_TYPE, rawAttributeType, null, null,
433 null, null, null);
434 }
435
436
437
438 /**
439 * Creates a new present filter with the provided information.
440 *
441 * @param attributeType The attribute type.
442 *
443 * @return The created present filter.
444 */
445 public static MatchedValuesFilter createPresentFilter(
446 AttributeType attributeType)
447 {
448 Validator.ensureNotNull(attributeType);
449 String rawAttributeType = attributeType.getNameOrOID();
450
451 MatchedValuesFilter filter =
452 new MatchedValuesFilter(PRESENT_TYPE, rawAttributeType, null, null,
453 null, null, null);
454 filter.attributeType = attributeType;
455
456 return filter;
457 }
458
459
460
461 /**
462 * Creates a new approxMatch filter with the provided information.
463 *
464 * @param rawAttributeType The raw, unprocessed attribute type.
465 * @param rawAssertionValue The raw, unprocessed assertion value.
466 *
467 * @return The created approxMatch filter.
468 */
469 public static MatchedValuesFilter createApproximateFilter(
470 String rawAttributeType,
471 ByteString rawAssertionValue)
472 {
473 Validator.ensureNotNull(rawAttributeType,rawAssertionValue);
474
475 return new MatchedValuesFilter(APPROXIMATE_MATCH_TYPE, rawAttributeType,
476 rawAssertionValue, null, null, null, null);
477 }
478
479
480
481 /**
482 * Creates a new approxMatch filter with the provided information.
483 *
484 * @param attributeType The attribute type.
485 * @param assertionValue The assertion value.
486 *
487 * @return The created approxMatch filter.
488 */
489 public static MatchedValuesFilter createApproximateFilter(
490 AttributeType attributeType,
491 AttributeValue assertionValue)
492 {
493 Validator.ensureNotNull(attributeType,assertionValue);
494 String rawAttributeType = attributeType.getNameOrOID();
495 ASN1OctetString rawAssertionValue =
496 assertionValue.getValue().toASN1OctetString();
497
498 MatchedValuesFilter filter =
499 new MatchedValuesFilter(APPROXIMATE_MATCH_TYPE, rawAttributeType,
500 rawAssertionValue, null, null, null, null);
501 filter.attributeType = attributeType;
502 filter.assertionValue = assertionValue;
503
504 return filter;
505 }
506
507
508
509 /**
510 * Creates a new extensibleMatch filter with the provided information.
511 *
512 * @param rawAttributeType The raw, unprocessed attribute type.
513 * @param matchingRuleID The matching rule ID.
514 * @param rawAssertionValue The raw, unprocessed assertion value.
515 *
516 * @return The created extensibleMatch filter.
517 */
518 public static MatchedValuesFilter createExtensibleMatchFilter(
519 String rawAttributeType,
520 String matchingRuleID,
521 ByteString rawAssertionValue)
522 {
523 Validator
524 .ensureNotNull(rawAttributeType, matchingRuleID, rawAssertionValue);
525 return new MatchedValuesFilter(EXTENSIBLE_MATCH_TYPE, rawAttributeType,
526 rawAssertionValue, null, null, null,
527 matchingRuleID);
528 }
529
530
531
532 /**
533 * Creates a new extensibleMatch filter with the provided information.
534 *
535 * @param attributeType The attribute type.
536 * @param matchingRule The matching rule.
537 * @param assertionValue The assertion value.
538 *
539 * @return The created extensibleMatch filter.
540 */
541 public static MatchedValuesFilter createExtensibleMatchFilter(
542 AttributeType attributeType,
543 MatchingRule matchingRule,
544 AttributeValue assertionValue)
545 {
546 Validator.ensureNotNull(attributeType, matchingRule, assertionValue);
547 String rawAttributeType = attributeType.getNameOrOID();
548 String matchingRuleID = matchingRule.getOID();
549 ASN1OctetString rawAssertionValue =
550 assertionValue.getValue().toASN1OctetString();
551
552 MatchedValuesFilter filter =
553 new MatchedValuesFilter(EXTENSIBLE_MATCH_TYPE, rawAttributeType,
554 rawAssertionValue, null, null, null,
555 matchingRuleID);
556 filter.attributeType = attributeType;
557 filter.assertionValue = assertionValue;
558 filter.matchingRule = matchingRule;
559
560 return filter;
561 }
562
563
564
565 /**
566 * Creates a new matched values filter from the provided LDAP filter.
567 *
568 * @param filter The LDAP filter to use for this matched values filter.
569 *
570 * @return The corresponding matched values filter.
571 *
572 * @throws LDAPException If the provided LDAP filter cannot be treated as a
573 * matched values filter.
574 */
575 public static MatchedValuesFilter createFromLDAPFilter(RawFilter filter)
576 throws LDAPException
577 {
578 switch (filter.getFilterType())
579 {
580 case AND:
581 case OR:
582 case NOT:
583 // These filter types cannot be used in a matched values filter.
584 Message message = ERR_MVFILTER_INVALID_LDAP_FILTER_TYPE.get(
585 String.valueOf(filter), String.valueOf(filter.getFilterType()));
586 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
587
588
589 case EQUALITY:
590 return new MatchedValuesFilter(EQUALITY_MATCH_TYPE,
591 filter.getAttributeType(),
592 filter.getAssertionValue(), null, null,
593 null, null);
594
595
596 case SUBSTRING:
597 return new MatchedValuesFilter(SUBSTRINGS_TYPE,
598 filter.getAttributeType(), null,
599 filter.getSubInitialElement(),
600 filter.getSubAnyElements(),
601 filter.getSubFinalElement(), null);
602
603
604 case GREATER_OR_EQUAL:
605 return new MatchedValuesFilter(GREATER_OR_EQUAL_TYPE,
606 filter.getAttributeType(),
607 filter.getAssertionValue(), null, null,
608 null, null);
609
610
611 case LESS_OR_EQUAL:
612 return new MatchedValuesFilter(LESS_OR_EQUAL_TYPE,
613 filter.getAttributeType(),
614 filter.getAssertionValue(), null, null,
615 null, null);
616
617
618 case PRESENT:
619 return new MatchedValuesFilter(PRESENT_TYPE, filter.getAttributeType(),
620 null, null, null, null, null);
621
622
623 case APPROXIMATE_MATCH:
624 return new MatchedValuesFilter(APPROXIMATE_MATCH_TYPE,
625 filter.getAttributeType(),
626 filter.getAssertionValue(), null, null,
627 null, null);
628
629
630 case EXTENSIBLE_MATCH:
631 if (filter.getDNAttributes())
632 {
633 // This cannot be represented in a matched values filter.
634 message = ERR_MVFILTER_INVALID_DN_ATTRIBUTES_FLAG.get(
635 String.valueOf(filter));
636 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
637 }
638 else
639 {
640 return new MatchedValuesFilter(EXTENSIBLE_MATCH_TYPE,
641 filter.getAttributeType(),
642 filter.getAssertionValue(), null, null,
643 null, filter.getMatchingRuleID());
644 }
645
646
647 default:
648 message = ERR_MVFILTER_INVALID_LDAP_FILTER_TYPE.get(
649 String.valueOf(filter), String.valueOf(filter.getFilterType()));
650 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
651 }
652 }
653
654
655
656 /**
657 * Encodes this matched values filter as an ASN.1 element.
658 *
659 * @return The ASN.1 element containing the encoded matched values filter.
660 */
661 public ASN1Element encode()
662 {
663 switch (matchType)
664 {
665 case EQUALITY_MATCH_TYPE:
666 case GREATER_OR_EQUAL_TYPE:
667 case LESS_OR_EQUAL_TYPE:
668 case APPROXIMATE_MATCH_TYPE:
669 // These will all be encoded in the same way.
670 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
671 elements.add(new ASN1OctetString(rawAttributeType));
672 elements.add(rawAssertionValue.toASN1OctetString());
673 return new ASN1Sequence(matchType, elements);
674
675
676 case SUBSTRINGS_TYPE:
677 ArrayList<ASN1Element> subElements = new ArrayList<ASN1Element>();
678 if (subInitial != null)
679 {
680 ASN1OctetString subInitialOS = subInitial.toASN1OctetString();
681 subInitialOS.setType(TYPE_SUBINITIAL);
682 subElements.add(subInitialOS);
683 }
684
685 if (subAny != null)
686 {
687 for (ByteString s : subAny)
688 {
689 ASN1OctetString os = s.toASN1OctetString();
690 os.setType(TYPE_SUBANY);
691 subElements.add(os);
692 }
693 }
694
695 if (subFinal != null)
696 {
697 ASN1OctetString subFinalOS = subFinal.toASN1OctetString();
698 subFinalOS.setType(TYPE_SUBFINAL);
699 subElements.add(subFinalOS);
700 }
701
702 elements = new ArrayList<ASN1Element>(2);
703 elements.add(new ASN1OctetString(rawAttributeType));
704 elements.add(new ASN1Sequence(subElements));
705 return new ASN1Sequence(matchType, elements);
706
707
708 case PRESENT_TYPE:
709 return new ASN1OctetString(matchType, rawAttributeType);
710
711
712 case EXTENSIBLE_MATCH_TYPE:
713 elements = new ArrayList<ASN1Element>(3);
714 if (matchingRuleID != null)
715 {
716 elements.add(new ASN1OctetString(TYPE_MATCHING_RULE_ID,
717 matchingRuleID));
718 }
719
720 if (rawAttributeType != null)
721 {
722 elements.add(new ASN1OctetString(TYPE_MATCHING_RULE_TYPE,
723 rawAttributeType));
724 }
725
726 ASN1OctetString valueOS = rawAssertionValue.toASN1OctetString();
727 valueOS.setType(TYPE_MATCHING_RULE_VALUE);
728 elements.add(valueOS);
729 return new ASN1Sequence(matchType, elements);
730
731
732 default:
733 return null;
734 }
735 }
736
737
738
739 /**
740 * Decodes the provided ASN.1 element as a matched values filter item.
741 *
742 * @param element The ASN.1 element to be decoded.
743 *
744 * @return The decoded matched values filter.
745 *
746 * @throws LDAPException If a problem occurs while attempting to decode the
747 * filter item.
748 */
749 public static MatchedValuesFilter decode(ASN1Element element)
750 throws LDAPException
751 {
752 switch (element.getType())
753 {
754 case EQUALITY_MATCH_TYPE:
755 case GREATER_OR_EQUAL_TYPE:
756 case LESS_OR_EQUAL_TYPE:
757 case APPROXIMATE_MATCH_TYPE:
758 // These will all be decoded in the same manner. The element must be a
759 // sequence consisting of the attribute type and assertion value.
760 try
761 {
762 ArrayList<ASN1Element> elements =
763 element.decodeAsSequence().elements();
764 if (elements.size() != 2)
765 {
766 Message message =
767 ERR_MVFILTER_INVALID_AVA_SEQUENCE_SIZE.get(elements.size());
768 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
769 }
770
771 String rawAttributeType =
772 elements.get(0).decodeAsOctetString().stringValue();
773
774 return new MatchedValuesFilter(element.getType(), rawAttributeType,
775 elements.get(1).decodeAsOctetString(),
776 null, null, null, null);
777 }
778 catch (LDAPException le)
779 {
780 throw le;
781 }
782 catch (Exception e)
783 {
784 if (debugEnabled())
785 {
786 TRACER.debugCaught(DebugLogLevel.ERROR, e);
787 }
788
789 Message message =
790 ERR_MVFILTER_CANNOT_DECODE_AVA.get(getExceptionMessage(e));
791 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
792 e);
793 }
794
795
796 case SUBSTRINGS_TYPE:
797 // This must be a sequence of two elements, where the second is a
798 // sequence of substring types.
799 try
800 {
801 ArrayList<ASN1Element> elements =
802 element.decodeAsSequence().elements();
803 if (elements.size() != 2)
804 {
805 Message message = ERR_MVFILTER_INVALID_SUBSTRING_SEQUENCE_SIZE.get(
806 elements.size());
807 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
808 }
809
810 ArrayList<ASN1Element> subElements =
811 elements.get(1).decodeAsSequence().elements();
812 if (subElements.isEmpty())
813 {
814 Message message = ERR_MVFILTER_NO_SUBSTRING_ELEMENTS.get();
815 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
816 }
817
818 String rawAttributeType =
819 elements.get(0).decodeAsOctetString().stringValue();
820
821 ByteString subInitial = null;
822 ArrayList<ByteString> subAny = null;
823 ByteString subFinal = null;
824 for (ASN1Element e : subElements)
825 {
826 switch (e.getType())
827 {
828 case TYPE_SUBINITIAL:
829 if (subInitial == null)
830 {
831 subInitial = e.decodeAsOctetString();
832 }
833 else
834 {
835 Message message = ERR_MVFILTER_MULTIPLE_SUBINITIALS.get();
836 throw new LDAPException(
837 LDAPResultCode.PROTOCOL_ERROR, message);
838 }
839 break;
840
841 case TYPE_SUBANY:
842 if (subAny == null)
843 {
844 subAny = new ArrayList<ByteString>();
845 }
846
847 subAny.add(e.decodeAsOctetString());
848 break;
849
850 case TYPE_SUBFINAL:
851 if (subFinal == null)
852 {
853 subFinal = e.decodeAsOctetString();
854 }
855 else
856 {
857 Message message = ERR_MVFILTER_MULTIPLE_SUBFINALS.get();
858 throw new LDAPException(
859 LDAPResultCode.PROTOCOL_ERROR, message);
860 }
861 break;
862
863 default:
864 Message message = ERR_MVFILTER_INVALID_SUBSTRING_ELEMENT_TYPE.
865 get(byteToHex(e.getType()));
866 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
867 }
868 }
869
870 return new MatchedValuesFilter(element.getType(), rawAttributeType,
871 null, subInitial, subAny, subFinal,
872 null);
873 }
874 catch (LDAPException le)
875 {
876 throw le;
877 }
878 catch (Exception e)
879 {
880 if (debugEnabled())
881 {
882 TRACER.debugCaught(DebugLogLevel.ERROR, e);
883 }
884
885 Message message =
886 ERR_MVFILTER_CANNOT_DECODE_SUBSTRINGS.get(getExceptionMessage(e));
887 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
888 e);
889 }
890
891
892 case PRESENT_TYPE:
893 // The element must be an ASN.1 octet string holding the attribute type.
894 try
895 {
896 String rawAttributeType = element.decodeAsOctetString().stringValue();
897
898 return new MatchedValuesFilter(element.getType(), rawAttributeType,
899 null, null, null, null, null);
900 }
901 catch (Exception e)
902 {
903 if (debugEnabled())
904 {
905 TRACER.debugCaught(DebugLogLevel.ERROR, e);
906 }
907
908 Message message = ERR_MVFILTER_CANNOT_DECODE_PRESENT_TYPE.get(
909 getExceptionMessage(e));
910 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
911 e);
912 }
913
914
915 case EXTENSIBLE_MATCH_TYPE:
916 // This must be a two or three element sequence with an assertion value
917 // as the last element and an attribute type and/or matching rule ID as
918 // the first element(s).
919 try
920 {
921 ArrayList<ASN1Element> elements =
922 element.decodeAsSequence().elements();
923 if ((elements.size() < 2) || (elements.size() > 3))
924 {
925 Message message = ERR_MVFILTER_INVALID_EXTENSIBLE_SEQUENCE_SIZE.get(
926 elements.size());
927 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
928 }
929
930
931 String rawAttributeType = null;
932 String matchingRuleID = null;
933 ASN1OctetString rawAssertionValue = null;
934 for (ASN1Element e : elements)
935 {
936 switch (e.getType())
937 {
938 case TYPE_MATCHING_RULE_ID:
939 if (matchingRuleID == null)
940 {
941 matchingRuleID = e.decodeAsOctetString().stringValue();
942 }
943 else
944 {
945 Message message =
946 ERR_MVFILTER_MULTIPLE_MATCHING_RULE_IDS.get();
947 throw new LDAPException(
948 LDAPResultCode.PROTOCOL_ERROR, message);
949 }
950 break;
951
952 case TYPE_MATCHING_RULE_TYPE:
953 if (rawAttributeType == null)
954 {
955 rawAttributeType = e.decodeAsOctetString().stringValue();
956 }
957 else
958 {
959 Message message = ERR_MVFILTER_MULTIPLE_ATTRIBUTE_TYPES.get();
960 throw new LDAPException(
961 LDAPResultCode.PROTOCOL_ERROR, message);
962 }
963 break;
964
965 case TYPE_MATCHING_RULE_VALUE:
966 if (rawAssertionValue == null)
967 {
968 rawAssertionValue = e.decodeAsOctetString();
969 }
970 else
971 {
972 Message message =
973 ERR_MVFILTER_MULTIPLE_ASSERTION_VALUES.get();
974 throw new LDAPException(
975 LDAPResultCode.PROTOCOL_ERROR, message);
976 }
977 break;
978
979 default:
980 Message message = ERR_MVFILTER_INVALID_EXTENSIBLE_ELEMENT_TYPE.
981 get(byteToHex(e.getType()));
982 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
983 }
984 }
985
986
987 return new MatchedValuesFilter(element.getType(), rawAttributeType,
988 rawAssertionValue, null, null, null,
989 matchingRuleID);
990 }
991 catch (LDAPException le)
992 {
993 throw le;
994 }
995 catch (Exception e)
996 {
997 if (debugEnabled())
998 {
999 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1000 }
1001
1002 Message message = ERR_MVFILTER_CANNOT_DECODE_EXTENSIBLE_MATCH.get(
1003 getExceptionMessage(e));
1004 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message,
1005 e);
1006 }
1007
1008
1009 default:
1010 Message message =
1011 ERR_MVFILTER_INVALID_ELEMENT_TYPE.get(byteToHex(element.getType()));
1012 throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
1013 }
1014 }
1015
1016
1017
1018 /**
1019 * Retrieves the match type for this matched values filter.
1020 *
1021 * @return The match type for this matched values filter.
1022 */
1023 public byte getMatchType()
1024 {
1025 return matchType;
1026 }
1027
1028
1029
1030 /**
1031 * Retrieves the raw, unprocessed attribute type for this matched values
1032 * filter.
1033 *
1034 * @return The raw, unprocessed attribute type for this matched values
1035 * filter, or <CODE>null</CODE> if there is none.
1036 */
1037 public String getRawAttributeType()
1038 {
1039 return rawAttributeType;
1040 }
1041
1042
1043
1044 /**
1045 * Specifies the raw, unprocessed attribute type for this matched values
1046 * filter.
1047 *
1048 * @param rawAttributeType The raw, unprocessed attribute type for this
1049 * matched values filter.
1050 */
1051 public void setRawAttributeType(String rawAttributeType)
1052 {
1053 this.rawAttributeType = rawAttributeType;
1054
1055 decoded = false;
1056 attributeType = null;
1057 approximateMatchingRule = null;
1058 equalityMatchingRule = null;
1059 orderingMatchingRule = null;
1060 substringMatchingRule = null;
1061 }
1062
1063
1064
1065 /**
1066 * Retrieves the attribute type for this matched values filter.
1067 *
1068 * @return The attribute type for this matched values filter, or
1069 * <CODE>null</CODE> if there is none.
1070 */
1071 public AttributeType getAttributeType()
1072 {
1073 if (attributeType == null)
1074 {
1075 if (rawAttributeType != null)
1076 {
1077 attributeType =
1078 DirectoryServer.getAttributeType(toLowerCase(rawAttributeType));
1079 if (attributeType == null)
1080 {
1081 attributeType =
1082 DirectoryServer.getDefaultAttributeType(rawAttributeType);
1083 }
1084 }
1085 }
1086
1087 return attributeType;
1088 }
1089
1090
1091
1092 /**
1093 * Specifies the attribute type for this matched values filter.
1094 *
1095 * @param attributeType The attribute type for this matched values filter.
1096 */
1097 public void setAttributeType(AttributeType attributeType)
1098 {
1099 this.attributeType = attributeType;
1100
1101 if (attributeType == null)
1102 {
1103 rawAttributeType = null;
1104 }
1105 else
1106 {
1107 rawAttributeType = attributeType.getNameOrOID();
1108 }
1109
1110 decoded = false;
1111 approximateMatchingRule = null;
1112 equalityMatchingRule = null;
1113 orderingMatchingRule = null;
1114 substringMatchingRule = null;
1115 }
1116
1117
1118
1119 /**
1120 * Retrieves the raw, unprocessed assertion value for this matched values
1121 * filter.
1122 *
1123 * @return The raw, unprocessed assertion value for this matched values
1124 * filter, or <CODE>null</CODE> if there is none.
1125 */
1126 public ByteString getRawAssertionValue()
1127 {
1128 return rawAssertionValue;
1129 }
1130
1131
1132
1133 /**
1134 * Specifies the raw, unprocessed assertion value for this matched values
1135 * filter.
1136 *
1137 * @param rawAssertionValue The raw, unprocessed assertion value for this
1138 * matched values filter.
1139 */
1140 public void setRawAssertionValue(ByteString rawAssertionValue)
1141 {
1142 this.rawAssertionValue = rawAssertionValue;
1143
1144 decoded = false;
1145 assertionValue = null;
1146 }
1147
1148
1149
1150 /**
1151 * Retrieves the assertion value for this matched values filter.
1152 *
1153 * @return The assertion value for this matched values filter, or
1154 * <CODE>null</CODE> if there is none.
1155 */
1156 public AttributeValue getAssertionValue()
1157 {
1158 if (assertionValue == null)
1159 {
1160 if (rawAssertionValue != null)
1161 {
1162 assertionValue = new AttributeValue(getAttributeType(),
1163 rawAssertionValue);
1164 }
1165 }
1166
1167 return assertionValue;
1168 }
1169
1170
1171
1172 /**
1173 * Specifies the assertion value for this matched values filter.
1174 *
1175 * @param assertionValue The assertion value for this matched values filter.
1176 */
1177 public void setAssertionValue(AttributeValue assertionValue)
1178 {
1179 this.assertionValue = assertionValue;
1180
1181 if (assertionValue == null)
1182 {
1183 rawAssertionValue = null;
1184 }
1185 else
1186 {
1187 rawAssertionValue = assertionValue.getValue().toASN1OctetString();
1188 }
1189
1190 decoded = false;
1191 }
1192
1193
1194
1195 /**
1196 * Retrieves the subInitial element for this matched values filter.
1197 *
1198 * @return The subInitial element for this matched values filter, or
1199 * <CODE>null</CODE> if there is none.
1200 */
1201 public ByteString getSubInitialElement()
1202 {
1203 return subInitial;
1204 }
1205
1206
1207
1208 /**
1209 * Specifies the subInitial element for this matched values filter.
1210 *
1211 * @param subInitial The subInitial element for this matched values filter.
1212 */
1213 public void setSubInitialElement(ByteString subInitial)
1214 {
1215 this.subInitial = subInitial;
1216
1217 decoded = false;
1218 normalizedSubInitial = null;
1219 }
1220
1221
1222
1223 /**
1224 * Retrieves the normalized form of the subInitial element.
1225 *
1226 * @return The normalized form of the subInitial element, or
1227 * <CODE>null</CODE> if there is none.
1228 */
1229 public ASN1OctetString getNormalizedSubInitialElement()
1230 {
1231 if (normalizedSubInitial == null)
1232 {
1233 if ((subInitial != null) && (getSubstringMatchingRule() != null))
1234 {
1235 try
1236 {
1237 normalizedSubInitial =
1238 getSubstringMatchingRule().normalizeSubstring(subInitial).
1239 toASN1OctetString();
1240 }
1241 catch (Exception e)
1242 {
1243 if (debugEnabled())
1244 {
1245 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1246 }
1247 }
1248 }
1249 }
1250
1251 return normalizedSubInitial;
1252 }
1253
1254
1255
1256 /**
1257 * Retrieves the set of subAny elements for this matched values filter.
1258 *
1259 * @return The set of subAny elements for this matched values filter. If
1260 * there are none, then the return value may be either
1261 * <CODE>null</CODE> or an empty list.
1262 */
1263 public List<ByteString> getSubAnyElements()
1264 {
1265 return subAny;
1266 }
1267
1268
1269
1270 /**
1271 * Specifies the set of subAny elements for this matched values filter.
1272 *
1273 * @param subAny The set of subAny elements for this matched values filter.
1274 */
1275 public void setSubAnyElements(List<ByteString> subAny)
1276 {
1277 this.subAny = subAny;
1278
1279 decoded = false;
1280 normalizedSubAny = null;
1281 }
1282
1283
1284
1285 /**
1286 * Retrieves the set of normalized subAny elements for this matched values
1287 * filter.
1288 *
1289 * @return The set of subAny elements for this matched values filter. If
1290 * there are none, then an empty list will be returned. If a
1291 * problem occurs while attempting to perform the normalization, then
1292 * <CODE>null</CODE> will be returned.
1293 */
1294 public List<ASN1OctetString> getNormalizedSubAnyElements()
1295 {
1296 if (normalizedSubAny == null)
1297 {
1298 if ((subAny == null) || (subAny.isEmpty()))
1299 {
1300 normalizedSubAny = new ArrayList<ASN1OctetString>(0);
1301 }
1302 else
1303 {
1304 if (getSubstringMatchingRule() == null)
1305 {
1306 return null;
1307 }
1308
1309 normalizedSubAny = new ArrayList<ASN1OctetString>();
1310 try
1311 {
1312 for (ByteString s : subAny)
1313 {
1314 normalizedSubAny.add(
1315 substringMatchingRule.normalizeSubstring(s).
1316 toASN1OctetString());
1317 }
1318 }
1319 catch (Exception e)
1320 {
1321 if (debugEnabled())
1322 {
1323 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1324 }
1325
1326 normalizedSubAny = null;
1327 }
1328 }
1329 }
1330
1331 return normalizedSubAny;
1332 }
1333
1334
1335
1336 /**
1337 * Retrieves the subFinal element for this matched values filter.
1338 *
1339 * @return The subFinal element for this matched values filter, or
1340 * <CODE>null</CODE> if there is none.
1341 */
1342 public ByteString getSubFinalElement()
1343 {
1344 return subFinal;
1345 }
1346
1347
1348
1349 /**
1350 * Specifies the subFinal element for this matched values filter.
1351 *
1352 * @param subFinal The subFinal element for this matched values filter.
1353 */
1354 public void setSubFinalElement(ByteString subFinal)
1355 {
1356 this.subFinal = subFinal;
1357
1358 decoded = false;
1359 normalizedSubFinal = null;
1360 }
1361
1362
1363
1364 /**
1365 * Retrieves the normalized form of the subFinal element.
1366 *
1367 * @return The normalized form of the subFinal element, or <CODE>null</CODE>
1368 * if there is none.
1369 */
1370 public ASN1OctetString getNormalizedSubFinalElement()
1371 {
1372 if (normalizedSubFinal == null)
1373 {
1374 if ((subFinal != null) && (getSubstringMatchingRule() != null))
1375 {
1376 try
1377 {
1378 normalizedSubFinal =
1379 getSubstringMatchingRule().normalizeSubstring(subFinal).
1380 toASN1OctetString();
1381 }
1382 catch (Exception e)
1383 {
1384 if (debugEnabled())
1385 {
1386 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1387 }
1388 }
1389 }
1390 }
1391
1392 return normalizedSubFinal;
1393 }
1394
1395
1396
1397 /**
1398 * Retrieves the matching rule ID for this matched values filter.
1399 *
1400 * @return The matching rule ID for this matched values filter, or
1401 * <CODE>null</CODE> if there is none.
1402 */
1403 public String getMatchingRuleID()
1404 {
1405 return matchingRuleID;
1406 }
1407
1408
1409
1410 /**
1411 * Specifies the matching rule ID for this matched values filter.
1412 *
1413 * @param matchingRuleID The matching rule ID for this matched values
1414 * filter.
1415 */
1416 public void setMatchingRuleID(String matchingRuleID)
1417 {
1418 this.matchingRuleID = matchingRuleID;
1419
1420 decoded = false;
1421 matchingRule = null;
1422 }
1423
1424
1425
1426 /**
1427 * Retrieves the matching rule for this matched values filter.
1428 *
1429 * @return The matching rule for this matched values filter, or
1430 * <CODE>null</CODE> if there is none.
1431 */
1432 public MatchingRule getMatchingRule()
1433 {
1434 if (matchingRule == null)
1435 {
1436 if (matchingRuleID != null)
1437 {
1438 matchingRule =
1439 DirectoryServer.getMatchingRule(toLowerCase(matchingRuleID));
1440 }
1441 }
1442
1443 return matchingRule;
1444 }
1445
1446
1447
1448 /**
1449 * Specifies the matching rule for this matched values filter.
1450 *
1451 * @param matchingRule The matching rule for this matched values filter.
1452 */
1453 public void setMatchingRule(MatchingRule matchingRule)
1454 {
1455 this.matchingRule = matchingRule;
1456
1457 if (matchingRule == null)
1458 {
1459 matchingRuleID = null;
1460 }
1461 else
1462 {
1463 matchingRuleID = matchingRule.getNameOrOID();
1464 }
1465
1466 decoded = false;
1467 }
1468
1469
1470
1471 /**
1472 * Retrieves the approximate matching rule that should be used for this
1473 * matched values filter.
1474 *
1475 * @return The approximate matching rule that should be used for this matched
1476 * values filter, or <CODE>null</CODE> if there is none.
1477 */
1478 public ApproximateMatchingRule getApproximateMatchingRule()
1479 {
1480 if (approximateMatchingRule == null)
1481 {
1482 AttributeType attrType = getAttributeType();
1483 if (attrType != null)
1484 {
1485 approximateMatchingRule = attrType.getApproximateMatchingRule();
1486 }
1487 }
1488
1489 return approximateMatchingRule;
1490 }
1491
1492
1493
1494 /**
1495 * Retrieves the equality matching rule that should be used for this matched
1496 * values filter.
1497 *
1498 * @return The equality matching rule that should be used for this matched
1499 * values filter, or <CODE>null</CODE> if there is none.
1500 */
1501 public EqualityMatchingRule getEqualityMatchingRule()
1502 {
1503 if (equalityMatchingRule == null)
1504 {
1505 AttributeType attrType = getAttributeType();
1506 if (attrType != null)
1507 {
1508 equalityMatchingRule = attrType.getEqualityMatchingRule();
1509 }
1510 }
1511
1512 return equalityMatchingRule;
1513 }
1514
1515
1516
1517 /**
1518 * Retrieves the ordering matching rule that should be used for this matched
1519 * values filter.
1520 *
1521 * @return The ordering matching rule that should be used for this matched
1522 * values filter, or <CODE>null</CODE> if there is none.
1523 */
1524 public OrderingMatchingRule getOrderingMatchingRule()
1525 {
1526 if (orderingMatchingRule == null)
1527 {
1528 AttributeType attrType = getAttributeType();
1529 if (attrType != null)
1530 {
1531 orderingMatchingRule = attrType.getOrderingMatchingRule();
1532 }
1533 }
1534
1535 return orderingMatchingRule;
1536 }
1537
1538
1539
1540 /**
1541 * Retrieves the substring matching rule that should be used for this matched
1542 * values filter.
1543 *
1544 * @return The substring matching rule that should be used for this matched
1545 * values filter, or <CODE>null</CODE> if there is none.
1546 */
1547 public SubstringMatchingRule getSubstringMatchingRule()
1548 {
1549 if (substringMatchingRule == null)
1550 {
1551 AttributeType attrType = getAttributeType();
1552 if (attrType != null)
1553 {
1554 substringMatchingRule = attrType.getSubstringMatchingRule();
1555 }
1556 }
1557
1558 return substringMatchingRule;
1559 }
1560
1561
1562
1563 /**
1564 * Decodes all components of the matched values filter so that they can be
1565 * referenced as member variables.
1566 */
1567 private void fullyDecode()
1568 {
1569 if (! decoded)
1570 {
1571 getAttributeType();
1572 getAssertionValue();
1573 getNormalizedSubInitialElement();
1574 getNormalizedSubAnyElements();
1575 getNormalizedSubFinalElement();
1576 getMatchingRule();
1577 getApproximateMatchingRule();
1578 getEqualityMatchingRule();
1579 getOrderingMatchingRule();
1580 getSubstringMatchingRule();
1581 decoded = true;
1582 }
1583 }
1584
1585
1586
1587 /**
1588 * Indicates whether the specified attribute value matches the criteria
1589 * defined in this matched values filter.
1590 *
1591 * @param type The attribute type with which the provided value is
1592 * associated.
1593 * @param value The attribute value for which to make the determination.
1594 *
1595 * @return <CODE>true</CODE> if the specified attribute value matches the
1596 * criteria defined in this matched values filter, or
1597 * <CODE>false</CODE> if not.
1598 */
1599 public boolean valueMatches(AttributeType type, AttributeValue value)
1600 {
1601 fullyDecode();
1602
1603 switch (matchType)
1604 {
1605 case EQUALITY_MATCH_TYPE:
1606 if ((attributeType != null) && (type != null) &&
1607 attributeType.equals(type) && (assertionValue != null) &&
1608 (value != null) && (equalityMatchingRule != null))
1609 {
1610 try
1611 {
1612 return equalityMatchingRule.areEqual(
1613 assertionValue.getNormalizedValue(),
1614 value.getNormalizedValue());
1615 }
1616 catch (Exception e)
1617 {
1618 if (debugEnabled())
1619 {
1620 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1621 }
1622
1623 return false;
1624 }
1625 }
1626 else
1627 {
1628 return false;
1629 }
1630
1631
1632 case SUBSTRINGS_TYPE:
1633 if ((attributeType != null) && (type != null) &&
1634 attributeType.equals(type) && (substringMatchingRule != null))
1635 {
1636 try
1637 {
1638 ArrayList<ByteString> normalizedSubAnyBS =
1639 new ArrayList<ByteString>(normalizedSubAny);
1640
1641 return substringMatchingRule.valueMatchesSubstring(
1642 value.getNormalizedValue(), normalizedSubInitial,
1643 normalizedSubAnyBS, normalizedSubFinal);
1644 }
1645 catch (Exception e)
1646 {
1647 if (debugEnabled())
1648 {
1649 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1650 }
1651
1652 return false;
1653 }
1654 }
1655 else
1656 {
1657 return false;
1658 }
1659
1660
1661 case GREATER_OR_EQUAL_TYPE:
1662 if ((attributeType != null) && (type != null) &&
1663 attributeType.equals(type) && (assertionValue != null) &&
1664 (value != null) && (orderingMatchingRule != null))
1665 {
1666 try
1667 {
1668 return (orderingMatchingRule.compareValues(
1669 assertionValue.getNormalizedValue(),
1670 value.getNormalizedValue()) >= 0);
1671 }
1672 catch (Exception e)
1673 {
1674 if (debugEnabled())
1675 {
1676 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1677 }
1678
1679 return false;
1680 }
1681 }
1682 else
1683 {
1684 return false;
1685 }
1686
1687
1688 case LESS_OR_EQUAL_TYPE:
1689 if ((attributeType != null) && (type != null) &&
1690 attributeType.equals(type) && (assertionValue != null) &&
1691 (value != null) && (orderingMatchingRule != null))
1692 {
1693 try
1694 {
1695 return (orderingMatchingRule.compareValues(
1696 assertionValue.getNormalizedValue(),
1697 value.getNormalizedValue()) <= 0);
1698 }
1699 catch (Exception e)
1700 {
1701 if (debugEnabled())
1702 {
1703 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1704 }
1705
1706 return false;
1707 }
1708 }
1709 else
1710 {
1711 return false;
1712 }
1713
1714
1715 case PRESENT_TYPE:
1716 return ((attributeType != null) && (type != null) &&
1717 attributeType.equals(type));
1718
1719
1720 case APPROXIMATE_MATCH_TYPE:
1721 if ((attributeType != null) && (type != null) &&
1722 attributeType.equals(type) && (assertionValue != null) &&
1723 (value != null) && (approximateMatchingRule != null))
1724 {
1725 try
1726 {
1727 ByteString nv1 = approximateMatchingRule.normalizeValue(
1728 assertionValue.getNormalizedValue());
1729 ByteString nv2 = approximateMatchingRule.normalizeValue(
1730 value.getNormalizedValue());
1731
1732 return approximateMatchingRule.approximatelyMatch(nv1, nv2);
1733 }
1734 catch (Exception e)
1735 {
1736 if (debugEnabled())
1737 {
1738 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1739 }
1740
1741 return false;
1742 }
1743 }
1744 else
1745 {
1746 return false;
1747 }
1748
1749
1750 case EXTENSIBLE_MATCH_TYPE:
1751 if ((assertionValue == null) || (value == null))
1752 {
1753 return false;
1754 }
1755
1756 if (attributeType == null)
1757 {
1758 if (matchingRule == null)
1759 {
1760 return false;
1761 }
1762
1763 try
1764 {
1765 ASN1OctetString nv1 =
1766 matchingRule.normalizeValue(value.getValue()).
1767 toASN1OctetString();
1768 ASN1OctetString nv2 =
1769 matchingRule.normalizeValue(assertionValue.getValue()).
1770 toASN1OctetString();
1771
1772 return (matchingRule.valuesMatch(nv1, nv2) == ConditionResult.TRUE);
1773 }
1774 catch (Exception e)
1775 {
1776 if (debugEnabled())
1777 {
1778 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1779 }
1780
1781 return false;
1782 }
1783 }
1784 else
1785 {
1786 if ((! attributeType.equals(type)) || (equalityMatchingRule == null))
1787 {
1788 return false;
1789 }
1790
1791 try
1792 {
1793 return equalityMatchingRule.areEqual(
1794 assertionValue.getNormalizedValue(),
1795 value.getNormalizedValue());
1796 }
1797 catch (Exception e)
1798 {
1799 if (debugEnabled())
1800 {
1801 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1802 }
1803
1804 return false;
1805 }
1806 }
1807
1808
1809 default:
1810 return false;
1811 }
1812 }
1813
1814
1815
1816 /**
1817 * Retrieves a string representation of this matched values filter, as an RFC
1818 * 2254-compliant filter string.
1819 *
1820 * @return A string representation of this matched values filter.
1821 */
1822 public String toString()
1823 {
1824 StringBuilder buffer = new StringBuilder();
1825 toString(buffer);
1826 return buffer.toString();
1827 }
1828
1829
1830
1831 /**
1832 * Appends a string representation of this matched values filter, as an RFC
1833 * 2254-compliant filter string, to the provided buffer.
1834 *
1835 * @param buffer The buffer to which the filter string should be appended.
1836 */
1837 public void toString(StringBuilder buffer)
1838 {
1839 switch (matchType)
1840 {
1841 case EQUALITY_MATCH_TYPE:
1842 buffer.append("(");
1843 buffer.append(rawAttributeType);
1844 buffer.append("=");
1845 RawFilter.valueToFilterString(buffer, rawAssertionValue);
1846 buffer.append(")");
1847 break;
1848
1849
1850 case SUBSTRINGS_TYPE:
1851 buffer.append("(");
1852 buffer.append(rawAttributeType);
1853 buffer.append("=");
1854 if (subInitial != null)
1855 {
1856 RawFilter.valueToFilterString(buffer, subInitial);
1857 }
1858
1859 if (subAny != null)
1860 {
1861 for (ByteString s : subAny)
1862 {
1863 buffer.append("*");
1864 RawFilter.valueToFilterString(buffer, s);
1865 }
1866 }
1867
1868 buffer.append("*");
1869 if (subFinal != null)
1870 {
1871 RawFilter.valueToFilterString(buffer, subFinal);
1872 }
1873 buffer.append(")");
1874 break;
1875
1876
1877 case GREATER_OR_EQUAL_TYPE:
1878 buffer.append("(");
1879 buffer.append(rawAttributeType);
1880 buffer.append(">=");
1881 RawFilter.valueToFilterString(buffer, rawAssertionValue);
1882 buffer.append(")");
1883 break;
1884
1885
1886 case LESS_OR_EQUAL_TYPE:
1887 buffer.append("(");
1888 buffer.append(rawAttributeType);
1889 buffer.append("<=");
1890 RawFilter.valueToFilterString(buffer, rawAssertionValue);
1891 buffer.append(")");
1892 break;
1893
1894
1895 case PRESENT_TYPE:
1896 buffer.append("(");
1897 buffer.append(rawAttributeType);
1898 buffer.append("=*)");
1899 break;
1900
1901
1902 case APPROXIMATE_MATCH_TYPE:
1903 buffer.append("(");
1904 buffer.append(rawAttributeType);
1905 buffer.append("~=");
1906 RawFilter.valueToFilterString(buffer, rawAssertionValue);
1907 buffer.append(")");
1908 break;
1909
1910
1911 case EXTENSIBLE_MATCH_TYPE:
1912 buffer.append("(");
1913
1914 if (rawAttributeType != null)
1915 {
1916 buffer.append(rawAttributeType);
1917 }
1918
1919 if (matchingRuleID != null)
1920 {
1921 buffer.append(":");
1922 buffer.append(matchingRuleID);
1923 }
1924
1925 buffer.append(":=");
1926 RawFilter.valueToFilterString(buffer, rawAssertionValue);
1927 buffer.append(")");
1928 break;
1929 }
1930 }
1931 }
1932