001/*
002 * Copyright 2008-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2008-2020 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2015-2020 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.monitors;
037
038
039
040import java.io.Serializable;
041import java.util.Arrays;
042import java.util.Collections;
043import java.util.Date;
044import java.util.Iterator;
045import java.util.LinkedHashMap;
046import java.util.List;
047import java.util.Map;
048
049import com.unboundid.ldap.sdk.Attribute;
050import com.unboundid.ldap.sdk.Entry;
051import com.unboundid.ldap.sdk.ReadOnlyEntry;
052import com.unboundid.util.Debug;
053import com.unboundid.util.DebugType;
054import com.unboundid.util.NotExtensible;
055import com.unboundid.util.StaticUtils;
056import com.unboundid.util.ThreadSafety;
057import com.unboundid.util.ThreadSafetyLevel;
058import com.unboundid.util.Validator;
059
060import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
061
062
063
064/**
065 * This class defines a generic monitor entry that provides access to monitor
066 * information provided by a Ping Identity, UnboundID, or Nokia/Alcatel-Lucent
067 * 8661 server instance.  Subclasses may provide specific methods for
068 * interpreting the information exposed by specific types of monitor entries.
069 * <BR>
070 * <BLOCKQUOTE>
071 *   <B>NOTE:</B>  This class, and other classes within the
072 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
073 *   supported for use against Ping Identity, UnboundID, and
074 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
075 *   for proprietary functionality or for external specifications that are not
076 *   considered stable or mature enough to be guaranteed to work in an
077 *   interoperable way with other types of LDAP servers.
078 * </BLOCKQUOTE>
079 * <BR>
080 * See the {@link MonitorManager} class for an example that demonstrates the
081 * process for retrieving all monitor entries available in the directory server
082 * and retrieving the information they provide using the generic API.
083 */
084@NotExtensible()
085@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
086public class MonitorEntry
087       implements Serializable
088{
089  /**
090   * The object class used for all monitor entries.  Specific monitor entries
091   * will have a subclass of this class.
092   */
093  static final String GENERIC_MONITOR_OC = "ds-monitor-entry";
094
095
096
097  /**
098   * The base DN for all monitor entries.
099   */
100  static final String MONITOR_BASE_DN = "cn=monitor";
101
102
103
104  /**
105   * The name of the attribute used to hold the name assigned to the monitor
106   * entry.
107   */
108  private static final String ATTR_MONITOR_NAME = "cn";
109
110
111
112  /**
113   * The serial version UID for this serializable class.
114   */
115  private static final long serialVersionUID = -8889119758772055683L;
116
117
118
119  // The entry containing the information used by this monitor entry object.
120  private final ReadOnlyEntry entry;
121
122  // The monitor object class for the associated monitor entry, if available.
123  private final String monitorClass;
124
125  // The monitor name for this monitor entry.
126  private final String monitorName;
127
128
129
130  /**
131   * Creates a new monitor entry from the information contained in the provided
132   * entry.
133   *
134   * @param  entry  The entry providing information to use for this monitor
135   *                entry.  It must not be {@code null}.
136   */
137  public MonitorEntry(final Entry entry)
138  {
139    Validator.ensureNotNull(entry);
140
141    this.entry = new ReadOnlyEntry(entry);
142
143    monitorClass = getMonitorClass(entry);
144    monitorName  = getString(ATTR_MONITOR_NAME);
145  }
146
147
148
149  /**
150   * Retrieves the DN for this monitor entry.
151   *
152   * @return  The DN for this monitor entry.
153   */
154  public final String getDN()
155  {
156    return entry.getDN();
157  }
158
159
160
161  /**
162   * Retrieves the {@code Entry} used to create this monitor entry.
163   *
164   * @return  The {@code Entry} used to create this monitor entry.
165   */
166  public final ReadOnlyEntry getEntry()
167  {
168    return entry;
169  }
170
171
172
173  /**
174   * Retrieves the name of the structural object class for this monitor entry.
175   *
176   * @return  The name of the structural object class for this monitor entry, or
177   *          the generic monitor object class if no appropriate subclass could
178   *          be identified.
179   */
180  public final String getMonitorClass()
181  {
182    return monitorClass;
183  }
184
185
186
187  /**
188   * Retrieves the monitor name for this monitor entry.
189   *
190   * @return  The monitor name for this monitor entry, or {@code null} if it was
191   *          not included in the monitor entry.
192   */
193  public final String getMonitorName()
194  {
195    return monitorName;
196  }
197
198
199
200  /**
201   * Retrieves a human-readable display name for this monitor entry.
202   *
203   * @return  A human-readable display name for this monitor entry.
204   */
205  public String getMonitorDisplayName()
206  {
207    return INFO_GENERIC_MONITOR_DISPNAME.get();
208  }
209
210
211
212  /**
213   * Retrieves a human-readable description name for this monitor entry.
214   *
215   * @return  A human-readable description name for this monitor entry.
216   */
217  public String getMonitorDescription()
218  {
219    return INFO_GENERIC_MONITOR_DESC.get();
220  }
221
222
223
224  /**
225   * Retrieves the set of parsed monitor attributes for this monitor entry,
226   * mapped from a unique identifier (in all lowercase characters) to the
227   * corresponding monitor attribute.
228   *
229   * @return  The set of parsed monitor attributes for this monitor entry.
230   */
231  public Map<String,MonitorAttribute> getMonitorAttributes()
232  {
233    // Retrieve a map of all attributes in the entry except cn and objectClass.
234    final LinkedHashMap<String,MonitorAttribute> attrs =
235         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
236
237    for (final Attribute a : entry.getAttributes())
238    {
239      final String lowerName = StaticUtils.toLowerCase(a.getName());
240      if (lowerName.equals("cn") || lowerName.equals("objectclass"))
241      {
242        continue;
243      }
244
245      attrs.put(lowerName,
246           new MonitorAttribute(lowerName, a.getName(), "", a.getValues()));
247    }
248
249    return Collections.unmodifiableMap(attrs);
250  }
251
252
253
254  /**
255   * Creates a monitor entry object from the provided entry.  An attempt will be
256   * made to decode the entry as an instance of the most appropriate subclass,
257   * but if that is not possible then it will be parsed as a generic monitor
258   * entry.
259   *
260   * @param  entry  The entry to be decoded as a monitor entry.
261   *
262   * @return  The decoded monitor entry of the appropriate subtype, or a generic
263   *          monitor entry if no appropriate subclass could be identified.
264   */
265  public static MonitorEntry decode(final Entry entry)
266  {
267    final String monitorClass = getMonitorClass(entry);
268
269    if (monitorClass.equalsIgnoreCase(
270             ActiveOperationsMonitorEntry.ACTIVE_OPERATIONS_MONITOR_OC))
271    {
272      return new ActiveOperationsMonitorEntry(entry);
273    }
274    else if (monitorClass.equalsIgnoreCase(
275                  BackendMonitorEntry.BACKEND_MONITOR_OC))
276    {
277      return new BackendMonitorEntry(entry);
278    }
279    else if (monitorClass.equalsIgnoreCase(
280                  ClientConnectionMonitorEntry.CLIENT_CONNECTION_MONITOR_OC))
281    {
282      return new ClientConnectionMonitorEntry(entry);
283    }
284    else if (monitorClass.equalsIgnoreCase(
285                  ConnectionHandlerMonitorEntry.CONNECTION_HANDLER_MONITOR_OC))
286    {
287      return new ConnectionHandlerMonitorEntry(entry);
288    }
289    else if (monitorClass.equalsIgnoreCase(
290                  DiskSpaceUsageMonitorEntry.DISK_SPACE_USAGE_MONITOR_OC))
291    {
292      return new DiskSpaceUsageMonitorEntry(entry);
293    }
294    else if (monitorClass.equalsIgnoreCase(
295                  EntryCacheMonitorEntry.ENTRY_CACHE_MONITOR_OC))
296    {
297      return new EntryCacheMonitorEntry(entry);
298    }
299    else if (monitorClass.equalsIgnoreCase(
300                  FIFOEntryCacheMonitorEntry.FIFO_ENTRY_CACHE_MONITOR_OC))
301    {
302      return new FIFOEntryCacheMonitorEntry(entry);
303    }
304    else if (monitorClass.equalsIgnoreCase(
305                  GaugeMonitorEntry.GAUGE_MONITOR_OC))
306    {
307      return new GaugeMonitorEntry(entry);
308    }
309    else if (monitorClass.equalsIgnoreCase(
310                  GeneralMonitorEntry.GENERAL_MONITOR_OC))
311    {
312      return new GeneralMonitorEntry(entry);
313    }
314    else if (monitorClass.equalsIgnoreCase(
315                  GroupCacheMonitorEntry.GROUP_CACHE_MONITOR_OC))
316    {
317      return new GroupCacheMonitorEntry(entry);
318    }
319    else if (monitorClass.equalsIgnoreCase(
320         HostSystemRecentCPUAndMemoryMonitorEntry.
321              HOST_SYSTEM_RECENT_CPU_AND_MEMORY_MONITOR_OC))
322    {
323      return new HostSystemRecentCPUAndMemoryMonitorEntry(entry);
324    }
325    else if (monitorClass.equalsIgnoreCase(
326                  IndexMonitorEntry.INDEX_MONITOR_OC))
327    {
328      return new IndexMonitorEntry(entry);
329    }
330    else if (monitorClass.equalsIgnoreCase(
331                  IndicatorGaugeMonitorEntry.INDICATOR_GAUGE_MONITOR_OC))
332    {
333      return new IndicatorGaugeMonitorEntry(entry);
334    }
335    else if (monitorClass.equalsIgnoreCase(
336                  JEEnvironmentMonitorEntry.JE_ENVIRONMENT_MONITOR_OC))
337    {
338      return new JEEnvironmentMonitorEntry(entry);
339    }
340    else if (monitorClass.equalsIgnoreCase(
341         LDAPExternalServerMonitorEntry.LDAP_EXTERNAL_SERVER_MONITOR_OC))
342    {
343      return new LDAPExternalServerMonitorEntry(entry);
344    }
345    else if (monitorClass.equalsIgnoreCase(
346                  LDAPStatisticsMonitorEntry.LDAP_STATISTICS_MONITOR_OC))
347    {
348      return new LDAPStatisticsMonitorEntry(entry);
349    }
350    else if (monitorClass.equalsIgnoreCase(
351         LoadBalancingAlgorithmMonitorEntry.
352              LOAD_BALANCING_ALGORITHM_MONITOR_OC))
353    {
354      return new LoadBalancingAlgorithmMonitorEntry(entry);
355    }
356    else if (monitorClass.equalsIgnoreCase(
357                  MemoryUsageMonitorEntry.MEMORY_USAGE_MONITOR_OC))
358    {
359      return new MemoryUsageMonitorEntry(entry);
360    }
361    else if (monitorClass.equalsIgnoreCase(
362                  NumericGaugeMonitorEntry.NUMERIC_GAUGE_MONITOR_OC))
363    {
364      return new NumericGaugeMonitorEntry(entry);
365    }
366    else if (monitorClass.equalsIgnoreCase(
367                  PerApplicationProcessingTimeHistogramMonitorEntry.
368                       PER_APPLICATION_PROCESSING_TIME_HISTOGRAM_MONITOR_OC))
369    {
370      return new PerApplicationProcessingTimeHistogramMonitorEntry(entry);
371    }
372    else if (monitorClass.equalsIgnoreCase(
373                  ProcessingTimeHistogramMonitorEntry.
374                       PROCESSING_TIME_HISTOGRAM_MONITOR_OC))
375    {
376      return new ProcessingTimeHistogramMonitorEntry(entry);
377    }
378    else if (monitorClass.equalsIgnoreCase(
379                  ReplicaMonitorEntry.REPLICA_MONITOR_OC))
380    {
381      return new ReplicaMonitorEntry(entry);
382    }
383    else if (monitorClass.equalsIgnoreCase(
384                  ReplicationServerMonitorEntry.REPLICATION_SERVER_MONITOR_OC))
385    {
386      return new ReplicationServerMonitorEntry(entry);
387    }
388    else if (monitorClass.equalsIgnoreCase(
389                  ReplicationSummaryMonitorEntry.
390                       REPLICATION_SUMMARY_MONITOR_OC))
391    {
392      return new ReplicationSummaryMonitorEntry(entry);
393    }
394    else if (monitorClass.equalsIgnoreCase(
395                  ResultCodeMonitorEntry.RESULT_CODE_MONITOR_OC))
396    {
397      return new ResultCodeMonitorEntry(entry);
398    }
399    else if (monitorClass.equalsIgnoreCase(
400                  StackTraceMonitorEntry.STACK_TRACE_MONITOR_OC))
401    {
402      return new StackTraceMonitorEntry(entry);
403    }
404    else if (monitorClass.equalsIgnoreCase(
405                  SystemInfoMonitorEntry.SYSTEM_INFO_MONITOR_OC))
406    {
407      return new SystemInfoMonitorEntry(entry);
408    }
409    else if (monitorClass.equalsIgnoreCase(
410                  TraditionalWorkQueueMonitorEntry.
411                       TRADITIONAL_WORK_QUEUE_MONITOR_OC))
412    {
413      return new TraditionalWorkQueueMonitorEntry(entry);
414    }
415    else if (monitorClass.equalsIgnoreCase(
416                  UnboundIDWorkQueueMonitorEntry.
417                       UNBOUNDID_WORK_QUEUE_MONITOR_OC))
418    {
419      return new UnboundIDWorkQueueMonitorEntry(entry);
420    }
421    else if (monitorClass.equalsIgnoreCase(
422                  VersionMonitorEntry.VERSION_MONITOR_OC))
423    {
424      return new VersionMonitorEntry(entry);
425    }
426
427    return new MonitorEntry(entry);
428  }
429
430
431
432  /**
433   * Gets the most appropriate monitor class from the provided entry.
434   *
435   * @param  entry  The entry from which to extract the monitor class.
436   *
437   * @return  The most appropriate monitor class from the provided entry, or the
438   *          generic monitor object class if no appropriate subclass could be
439   *          identified.
440   */
441  private static String getMonitorClass(final Entry entry)
442  {
443    String monitorOC = null;
444    final String[] ocNames = entry.getObjectClassValues();
445    for (final String oc : ocNames)
446    {
447      if (oc.equalsIgnoreCase("top") ||
448          oc.equalsIgnoreCase("extensibleObject") ||
449          oc.equalsIgnoreCase(GENERIC_MONITOR_OC))
450      {
451        // This isn't the class we're looking for.
452        continue;
453      }
454      else if (oc.equalsIgnoreCase(
455                    NumericGaugeMonitorEntry.NUMERIC_GAUGE_MONITOR_OC) ||
456               oc.equalsIgnoreCase(
457                    IndicatorGaugeMonitorEntry.INDICATOR_GAUGE_MONITOR_OC))
458      {
459        // These classes are subclasses of the base gauge monitor class.
460        // We'll allow them even if the monitor class is already set.
461        monitorOC = oc;
462      }
463      else if (oc.equalsIgnoreCase(GaugeMonitorEntry.GAUGE_MONITOR_OC))
464      {
465        // This is a superclass for the numeric and indicator gauge classes.
466        // We'll use it only if the monitor class isn't set, but we won't
467        // complain if the monitor class is already set.
468        if (monitorOC == null)
469        {
470          monitorOC = oc;
471        }
472      }
473      else
474      {
475        if (monitorOC != null)
476        {
477          if (Debug.debugEnabled(DebugType.MONITOR))
478          {
479            Debug.debugMonitor(entry,
480                 "Multiple monitor subclasses detected:  " + monitorOC +
481                      " and " + oc);
482          }
483        }
484
485        monitorOC = oc;
486      }
487    }
488
489    if (monitorOC == null)
490    {
491      if (entry.hasObjectClass(GENERIC_MONITOR_OC))
492      {
493        Debug.debugMonitor(entry, "No appropriate monitor subclass");
494      }
495      else
496      {
497        Debug.debugMonitor(entry, "Missing the generic monitor class");
498      }
499
500      return GENERIC_MONITOR_OC;
501    }
502    else
503    {
504      return monitorOC;
505    }
506  }
507
508
509
510  /**
511   * Retrieves the value of the specified attribute as a {@code Boolean} object.
512   *
513   * @param  attributeName  The name of the target attribute.
514   *
515   * @return  The {@code Boolean} object parsed from the specified attribute, or
516   *          {@code null} if the attribute does not exist in the entry or it
517   *          cannot be parsed as a {@code Boolean} value.
518   */
519  protected final Boolean getBoolean(final String attributeName)
520  {
521    final String valueStr = entry.getAttributeValue(attributeName);
522    if (valueStr == null)
523    {
524      if (Debug.debugEnabled(DebugType.MONITOR))
525      {
526        Debug.debugMonitor(entry, "No value for Boolean attribute " +
527             attributeName);
528      }
529
530      return null;
531    }
532    else if (valueStr.equalsIgnoreCase("true"))
533    {
534      return Boolean.TRUE;
535    }
536    else if (valueStr.equalsIgnoreCase("false"))
537    {
538      return Boolean.FALSE;
539    }
540    else
541    {
542      if (Debug.debugEnabled(DebugType.MONITOR))
543      {
544        Debug.debugMonitor(entry,
545             "Invalid value '" + valueStr + "' for Boolean attribute " +
546                  attributeName);
547      }
548
549      return null;
550    }
551  }
552
553
554
555  /**
556   * Retrieves the value of the specified attribute as a {@code Date} object.
557   *
558   * @param  attributeName  The name of the target attribute.
559   *
560   * @return  The {@code Date} object parsed from the specified attribute, or
561   *          {@code null} if the attribute does not exist in the entry or it
562   *          cannot be parsed as a {@code Date} value.
563   */
564  protected final Date getDate(final String attributeName)
565  {
566    final String valueStr = entry.getAttributeValue(attributeName);
567    if (valueStr == null)
568    {
569      if (Debug.debugEnabled(DebugType.MONITOR))
570      {
571        Debug.debugMonitor(entry, "No value for Date attribute " +
572             attributeName);
573      }
574
575      return null;
576    }
577    else
578    {
579      try
580      {
581        return StaticUtils.decodeGeneralizedTime(valueStr);
582      }
583      catch (final Exception e)
584      {
585        Debug.debugException(e);
586
587        if (Debug.debugEnabled(DebugType.MONITOR))
588        {
589          Debug.debugMonitor(entry,
590               "Invalid value '" + valueStr + "' for Date attribute " +
591                    attributeName);
592        }
593
594        return null;
595      }
596    }
597  }
598
599
600
601  /**
602   * Retrieves the value of the specified attribute as a {@code Double} object.
603   *
604   * @param  attributeName  The name of the target attribute.
605   *
606   * @return  The {@code Double} object parsed from the specified attribute, or
607   *          {@code null} if the attribute does not exist in the entry or it
608   *          cannot be parsed as a {@code Double} value.
609   */
610  protected final Double getDouble(final String attributeName)
611  {
612    final String valueStr = entry.getAttributeValue(attributeName);
613    if (valueStr == null)
614    {
615      if (Debug.debugEnabled(DebugType.MONITOR))
616      {
617        Debug.debugMonitor(entry, "No value for Double attribute " +
618             attributeName);
619      }
620
621      return null;
622    }
623    else
624    {
625      try
626      {
627        return Double.parseDouble(valueStr);
628      }
629      catch (final Exception e)
630      {
631        Debug.debugException(e);
632
633        if (Debug.debugEnabled(DebugType.MONITOR))
634        {
635          Debug.debugMonitor(entry,
636               "Invalid value '" + valueStr + "' for Double attribute " +
637                    attributeName);
638        }
639
640        return null;
641      }
642    }
643  }
644
645
646
647  /**
648   * Retrieves the value of the specified attribute as an {@code Integer}
649   * object.
650   *
651   * @param  attributeName  The name of the target attribute.
652   *
653   * @return  The {@code Integer} object parsed from the specified attribute, or
654   *          {@code null} if the attribute does not exist in the entry or it
655   *          cannot be parsed as an {@code Integer} value.
656   */
657  protected final Integer getInteger(final String attributeName)
658  {
659    final String valueStr = entry.getAttributeValue(attributeName);
660    if (valueStr == null)
661    {
662      if (Debug.debugEnabled(DebugType.MONITOR))
663      {
664        Debug.debugMonitor(entry, "No value for Integer attribute " +
665             attributeName);
666      }
667
668      return null;
669    }
670    else
671    {
672      try
673      {
674        return Integer.parseInt(valueStr);
675      }
676      catch (final Exception e)
677      {
678        Debug.debugException(e);
679
680        if (Debug.debugEnabled(DebugType.MONITOR))
681        {
682          Debug.debugMonitor(entry,
683               "Invalid value '" + valueStr + "' for Integer attribute " +
684                    attributeName);
685        }
686
687        return null;
688      }
689    }
690  }
691
692
693
694  /**
695   * Retrieves the value of the specified attribute as a {@code Long} object.
696   *
697   * @param  attributeName  The name of the target attribute.
698   *
699   * @return  The {@code Long} object parsed from the specified attribute, or
700   *          {@code null} if the attribute does not exist in the entry or it
701   *          cannot be parsed as a {@code Long} value.
702   */
703  protected final Long getLong(final String attributeName)
704  {
705    final String valueStr = entry.getAttributeValue(attributeName);
706    if (valueStr == null)
707    {
708      if (Debug.debugEnabled(DebugType.MONITOR))
709      {
710        Debug.debugMonitor(entry,
711             "No value for Long attribute " + attributeName);
712      }
713
714      return null;
715    }
716    else
717    {
718      try
719      {
720        return Long.parseLong(valueStr);
721      }
722      catch (final Exception e)
723      {
724        Debug.debugException(e);
725
726        if (Debug.debugEnabled(DebugType.MONITOR))
727        {
728          Debug.debugMonitor(entry,
729               "Invalid value '" + valueStr + "' for Long attribute " +
730                    attributeName);
731        }
732
733        return null;
734      }
735    }
736  }
737
738
739
740  /**
741   * Retrieves the value of the specified attribute as a string.
742   *
743   * @param  attributeName  The name of the target attribute.
744   *
745   * @return  The string value of the specified attribute, or {@code null} if it
746   *          does not exist in the entry.
747   */
748  protected final String getString(final String attributeName)
749  {
750    final String valueStr = entry.getAttributeValue(attributeName);
751    if ((valueStr == null) && Debug.debugEnabled(DebugType.MONITOR))
752    {
753      Debug.debugMonitor(entry,
754           "No value for string attribute " + attributeName);
755    }
756
757    return valueStr;
758  }
759
760
761
762  /**
763   * Retrieves the set of values of the specified attribute as a string list.
764   *
765   * @param  attributeName  The name of the target attribute.
766   *
767   * @return  The string values of the specified attribute, or an empty list if
768   *          the specified attribute does not exist in the entry.
769   */
770  protected final List<String> getStrings(final String attributeName)
771  {
772    final String[] valueStrs = entry.getAttributeValues(attributeName);
773    if (valueStrs == null)
774    {
775      if (Debug.debugEnabled(DebugType.MONITOR))
776      {
777        Debug.debugMonitor(entry,
778             "No values for string attribute " + attributeName);
779      }
780
781      return Collections.emptyList();
782    }
783
784    return Collections.unmodifiableList(Arrays.asList(valueStrs));
785  }
786
787
788
789  /**
790   * Adds a new monitor attribute to the specified map using the provided
791   * information.
792   *
793   * @param  attrs        The attribute map to which the information should be
794   *                      added.
795   * @param  name         The name to use for this monitor attribute.  It must
796   *                      be unique among all other monitor attribute names for
797   *                      the associated monitor entry.
798   * @param  displayName  The human-readable display name for the monitor
799   *                      attribute.
800   * @param  description  The human-readable description for the monitor
801   *                      attribute.
802   * @param  value        The value for the monitor attribute.
803   */
804  protected static void addMonitorAttribute(
805                             final Map<String,MonitorAttribute> attrs,
806                             final String name, final String displayName,
807                             final String description, final Boolean value)
808  {
809    final String lowerName = StaticUtils.toLowerCase(name);
810
811    final MonitorAttribute a =
812         new MonitorAttribute(lowerName, displayName, description, value);
813    attrs.put(lowerName, a);
814  }
815
816
817
818  /**
819   * Adds a new monitor attribute to the specified map using the provided
820   * information.
821   *
822   * @param  attrs        The attribute map to which the information should be
823   *                      added.
824   * @param  name         The name to use for this monitor attribute.  It must
825   *                      be unique among all other monitor attribute names for
826   *                      the associated monitor entry.
827   * @param  displayName  The human-readable display name for the monitor
828   *                      attribute.
829   * @param  description  The human-readable description for the monitor
830   *                      attribute.
831   * @param  value        The value for the monitor attribute.
832   */
833  protected static void addMonitorAttribute(
834                             final Map<String,MonitorAttribute> attrs,
835                             final String name, final String displayName,
836                             final String description, final Date value)
837  {
838    final String lowerName = StaticUtils.toLowerCase(name);
839
840    final MonitorAttribute a =
841         new MonitorAttribute(lowerName, displayName, description, value);
842    attrs.put(lowerName, a);
843  }
844
845
846
847  /**
848   * Adds a new monitor attribute to the specified map using the provided
849   * information.
850   *
851   * @param  attrs        The attribute map to which the information should be
852   *                      added.
853   * @param  name         The name to use for this monitor attribute.  It must
854   *                      be unique among all other monitor attribute names for
855   *                      the associated monitor entry.
856   * @param  displayName  The human-readable display name for the monitor
857   *                      attribute.
858   * @param  description  The human-readable description for the monitor
859   *                      attribute.
860   * @param  value        The value for the monitor attribute.
861   */
862  protected static void addMonitorAttribute(
863                             final Map<String,MonitorAttribute> attrs,
864                             final String name, final String displayName,
865                             final String description, final Double value)
866  {
867    final String lowerName = StaticUtils.toLowerCase(name);
868
869    final MonitorAttribute a =
870         new MonitorAttribute(lowerName, displayName, description, value);
871    attrs.put(lowerName, a);
872  }
873
874
875
876  /**
877   * Adds a new monitor attribute to the specified map using the provided
878   * information.
879   *
880   * @param  attrs        The attribute map to which the information should be
881   *                      added.
882   * @param  name         The name to use for this monitor attribute.  It must
883   *                      be unique among all other monitor attribute names for
884   *                      the associated monitor entry.
885   * @param  displayName  The human-readable display name for the monitor
886   *                      attribute.
887   * @param  description  The human-readable description for the monitor
888   *                      attribute.
889   * @param  value        The value for the monitor attribute.
890   */
891  protected static void addMonitorAttribute(
892                             final Map<String,MonitorAttribute> attrs,
893                             final String name, final String displayName,
894                             final String description, final Integer value)
895  {
896    final String lowerName = StaticUtils.toLowerCase(name);
897
898    final MonitorAttribute a =
899         new MonitorAttribute(lowerName, displayName, description, value);
900    attrs.put(lowerName, a);
901  }
902
903
904
905  /**
906   * Adds a new monitor attribute to the specified map using the provided
907   * information.
908   *
909   * @param  attrs        The attribute map to which the information should be
910   *                      added.
911   * @param  name         The name to use for this monitor attribute.  It must
912   *                      be unique among all other monitor attribute names for
913   *                      the associated monitor entry.
914   * @param  displayName  The human-readable display name for the monitor
915   *                      attribute.
916   * @param  description  The human-readable description for the monitor
917   *                      attribute.
918   * @param  value        The value for the monitor attribute.
919   */
920  protected static void addMonitorAttribute(
921                             final Map<String,MonitorAttribute> attrs,
922                             final String name, final String displayName,
923                             final String description, final Long value)
924  {
925    final String lowerName = StaticUtils.toLowerCase(name);
926
927    final MonitorAttribute a =
928         new MonitorAttribute(lowerName, displayName, description, value);
929    attrs.put(lowerName, a);
930  }
931
932
933
934  /**
935   * Adds a new monitor attribute to the specified map using the provided
936   * information.
937   *
938   * @param  attrs        The attribute map to which the information should be
939   *                      added.
940   * @param  name         The name to use for this monitor attribute.  It must
941   *                      be unique among all other monitor attribute names for
942   *                      the associated monitor entry.
943   * @param  displayName  The human-readable display name for the monitor
944   *                      attribute.
945   * @param  description  The human-readable description for the monitor
946   *                      attribute.
947   * @param  value        The value for the monitor attribute.
948   */
949  protected static void addMonitorAttribute(
950                             final Map<String,MonitorAttribute> attrs,
951                             final String name, final String displayName,
952                             final String description, final String value)
953  {
954    final String lowerName = StaticUtils.toLowerCase(name);
955
956    final MonitorAttribute a =
957         new MonitorAttribute(lowerName, displayName, description, value);
958    attrs.put(lowerName, a);
959  }
960
961
962
963  /**
964   * Adds a new monitor attribute to the specified map using the provided
965   * information.
966   *
967   * @param  attrs        The attribute map to which the information should be
968   *                      added.
969   * @param  name         The name to use for this monitor attribute.  It must
970   *                      be unique among all other monitor attribute names for
971   *                      the associated monitor entry.
972   * @param  displayName  The human-readable display name for the monitor
973   *                      attribute.
974   * @param  description  The human-readable description for the monitor
975   *                      attribute.
976   * @param  values       The set of values for the monitor attribute.
977   */
978  protected static void addMonitorAttribute(
979                             final Map<String,MonitorAttribute> attrs,
980                             final String name, final String displayName,
981                             final String description,
982                             final List<String> values)
983  {
984    final String lowerName = StaticUtils.toLowerCase(name);
985
986    final MonitorAttribute a =
987         new MonitorAttribute(lowerName, displayName, description,
988                              values.toArray(new String[values.size()]));
989    attrs.put(lowerName, a);
990  }
991
992
993
994  /**
995   * Retrieves a string representation of this monitor entry.
996   *
997   * @return  A string representation of this monitor entry.
998   */
999  @Override()
1000  public final String toString()
1001  {
1002    final StringBuilder buffer = new StringBuilder();
1003    toString(buffer);
1004    return buffer.toString();
1005  }
1006
1007
1008
1009  /**
1010   * Appends a string representation of this monitor entry to the provided
1011   * buffer.
1012   *
1013   * @param  buffer  The buffer to which the information should be appended.
1014   */
1015  public final void toString(final StringBuilder buffer)
1016  {
1017    buffer.append("MonitorEntry(dn='");
1018    buffer.append(entry.getDN());
1019    buffer.append("', monitorClass='");
1020    buffer.append(monitorClass);
1021    buffer.append('\'');
1022
1023    final Iterator<MonitorAttribute> iterator =
1024         getMonitorAttributes().values().iterator();
1025    while (iterator.hasNext())
1026    {
1027      buffer.append(iterator.next());
1028      if (iterator.hasNext())
1029      {
1030        buffer.append(", ");
1031      }
1032    }
1033
1034    buffer.append(')');
1035  }
1036}