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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2008-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027
028package org.opends.guitools.controlpanel.ui.nodes;
029
030import javax.swing.Icon;
031import javax.swing.tree.DefaultMutableTreeNode;
032
033import org.opends.guitools.controlpanel.browser.BasicNodeError;
034import org.opends.server.types.DN;
035import org.opends.server.types.LDAPURL;
036import org.opends.server.types.RDN;
037
038/**
039 * The basic node used to render entries in the 'Manage Entries' tree.
040 *
041 */
042public class BasicNode extends DefaultMutableTreeNode {
043
044  private static final long serialVersionUID = 5441658731908509872L;
045  private String localDn;
046  private String localRdn;
047  private String localRdnWithAttributeName;
048  private LDAPURL remoteUrl;
049  private String remoteRdn;
050  private String remoteRdnWithAttributeName;
051
052  private boolean isLeaf;
053  private boolean refreshNeededOnExpansion = true;
054  private boolean obsolete;
055  private BasicNodeError error;
056
057  private String[] referral;
058  private int numSubOrdinates;
059
060  /**
061   * This is required for the case where there is an undefined number of
062   * subordinates (for instance in the case of the changelog).
063   */
064  private boolean hasSubOrdinates;
065
066  private String displayName;
067  private Icon icon;
068  private int fontStyle;
069
070  private boolean sizeLimitReached;
071
072  private String[] objectClassValues;
073
074  /**
075   * Constructor.
076   * @param dn the DN of the entry.
077   */
078  public BasicNode(String dn) {
079    localDn = dn;
080    localRdn = extractRDN(localDn);
081    localRdnWithAttributeName = extractRDN(localDn, true);
082    isLeaf = true;
083    refreshNeededOnExpansion = true;
084    numSubOrdinates = -1;
085    hasSubOrdinates = false;
086    displayName = "";
087  }
088
089
090  /**
091   * Returns the DN of the local entry.
092   * @return the DN of the local entry.
093   */
094  public String getDN() {
095    return localDn;
096  }
097
098  /**
099   * Returns the RDN value of the local entry.
100   * @return the RDN value of the local entry.
101   */
102  public String getRDN() {
103    return localRdn;
104  }
105
106  /**
107   * Returns the RDN (with the attribute name) of the local entry.
108   * @return the RDN (with the attribute name) of the local entry.
109   */
110  public String getRDNWithAttributeName() {
111    return localRdnWithAttributeName;
112  }
113
114  /**
115   * Returns the URL of the remote entry (if the node does not represent a
116   * referral it will be <CODE>null</CODE>).
117   * @return the URL of the remote entry (if the node does not represent a
118   * referral it will be <CODE>null</CODE>).
119   */
120  public LDAPURL getRemoteUrl() {
121    return remoteUrl;
122  }
123
124  /**
125   * Sets the remote URL of the node.
126   * @param url the remote URL of the node.
127   */
128  public void setRemoteUrl(LDAPURL url) {
129    remoteUrl = url;
130    if (remoteUrl != null)
131    {
132      remoteRdn = extractRDN(remoteUrl.getRawBaseDN());
133      remoteRdnWithAttributeName = extractRDN(remoteUrl.getRawBaseDN(), true);
134    }
135    else
136    {
137      remoteRdn = null;
138      remoteRdnWithAttributeName = null;
139    }
140  }
141
142  /**
143   * Sets the remote URL of the node.
144   * @param url the remote URL of the node.
145   */
146  public void setRemoteUrl(String url) {
147    try
148    {
149      if (url == null)
150      {
151        remoteUrl = null;
152      }
153      else
154      {
155        remoteUrl = LDAPURL.decode(url, false);
156      }
157      if (remoteUrl == null) {
158        remoteRdn = null;
159        remoteRdnWithAttributeName = null;
160      }
161      else {
162        remoteRdn = extractRDN(remoteUrl.getRawBaseDN());
163        remoteRdnWithAttributeName = extractRDN(remoteUrl.getRawBaseDN(), true);
164      }
165    }
166    catch (Throwable t)
167    {
168      throw new IllegalArgumentException(
169          "The provided url: "+url+" is not valid:"+t, t);
170    }
171  }
172
173  /**
174   * Returns the RDN value of the remote entry.  If the node does not
175   * represent a referral it will return <CODE>null</CODE>.
176   * @return the RDN value of the remote entry.
177   */
178  public String getRemoteRDN() {
179    return remoteRdn;
180  }
181
182  /**
183   * Returns the RDN value of the remote entry (with the name of the attribute).
184   * If the node does not represent a referral it will return <CODE>null</CODE>.
185   * @return the RDN value of the remote entry (with the name of the attribute).
186   */
187  public String getRemoteRDNWithAttributeName() {
188    return remoteRdnWithAttributeName;
189  }
190
191
192  /**
193   * Sets whether the node is a leaf or not.
194   * @param isLeaf whether the node is a leaf or not.
195   */
196  public void setLeaf(boolean isLeaf) {
197    this.isLeaf = isLeaf;
198  }
199
200  /**
201   * Returns <CODE>true</CODE> if the node is a leaf and <CODE>false</CODE>
202   * otherwise.
203   * @return <CODE>true</CODE> if the node is a leaf and <CODE>false</CODE>
204   * otherwise.
205   */
206  public boolean isLeaf() {
207    return isLeaf;
208  }
209
210  /**
211   * Returns <CODE>true</CODE> if the node must be refreshed when it is expanded
212   * and <CODE>false</CODE> otherwise.
213   * @return <CODE>true</CODE> if the node must be refreshed when it is expanded
214   * and <CODE>false</CODE> otherwise.
215   */
216  public boolean isRefreshNeededOnExpansion() {
217    return refreshNeededOnExpansion;
218  }
219
220  /**
221   * Sets whether the node must be refreshed when it is expanded or not.
222   * @param refreshNeededOnExpansion  whether the node must be refreshed when it
223   * is expanded or not.
224   */
225  public void setRefreshNeededOnExpansion(boolean refreshNeededOnExpansion) {
226    this.refreshNeededOnExpansion = refreshNeededOnExpansion;
227  }
228
229  /**
230   * Returns whether the node is obsolete (and must be refreshed) or not.
231   * @return <CODE>true</CODE> if the node is obsolete and <CODE>false</CODE>
232   * otherwise.
233   */
234  public boolean isObsolete() {
235    return obsolete;
236  }
237
238  /**
239   * Sets whether this is node is obsolete (and must be refreshed) or not.
240   * @param obsolete whether this is node is obsolete (and must be refreshed) or
241   * not.
242   */
243  public void setObsolete(boolean obsolete) {
244    this.obsolete = obsolete;
245  }
246
247  /**
248   * Returns the error that occurred when updating the node.  Returns
249   * <CODE>null</CODE> if no error occurred.
250   * @return the error that occurred when updating the node.  Returns
251   * <CODE>null</CODE> if no error occurred.
252   */
253  public BasicNodeError getError() {
254    return error;
255  }
256
257  /**
258   * Sets the error that occurred when updating the node.
259   * @param error the error.
260   */
261  public void setError(BasicNodeError error) {
262    this.error = error;
263  }
264
265
266  /**
267   * Cached LDAP attributes
268   */
269
270  /**
271   * Returns the number of subordinates of the entry.
272   * @return the number of subordinates of the entry.
273   */
274  public int getNumSubOrdinates() {
275    return numSubOrdinates;
276  }
277
278  /**
279   * Sets the number of subordinates of the entry.
280   * @param number the number of subordinates of the entry.
281   */
282  public void setNumSubOrdinates(int number) {
283    numSubOrdinates = number;
284  }
285
286  /**
287   * Returns whether the entry has subordinates or not.
288   * @return {@code true} if the entry has subordinates and {@code false}
289   * otherwise.
290   */
291  public boolean hasSubOrdinates() {
292    return hasSubOrdinates;
293  }
294
295  /**
296   * Sets the whether the entry has subordinates or not.
297   * @param hasSubOrdinates whether the entry has subordinates or not.
298   */
299  public void setHasSubOrdinates(boolean hasSubOrdinates) {
300    this.hasSubOrdinates = hasSubOrdinates;
301  }
302
303  /**
304   * Returns the referrals of the entry. Returns <CODE>null</CODE> if this node
305   * is not a referral.
306   * @return the referrals of the entry. Returns <CODE>null</CODE> if this node
307   * is not a referral.
308   */
309  public String[] getReferral() {
310    return referral;
311  }
312
313  /**
314   * Sets the referrals of the entry.
315   * @param referral the referrals of the entry.
316   */
317  public void setReferral(String[] referral) {
318    this.referral = referral;
319  }
320
321
322  /**
323   * Rendering
324   */
325  /** {@inheritDoc} */
326  public String toString() {
327    return getDisplayName();
328  }
329
330  /**
331   * Returns the label that will be used to display the entry.
332   * @return the label that will be used to display the entry.
333   */
334  public String getDisplayName() {
335    return displayName;
336  }
337
338  /**
339   * Sets the label that will be used to display the entry.
340   * @param name the label that will be used to display the entry.
341   */
342  public void setDisplayName(String name) {
343    displayName = name;
344  }
345
346  /**
347   * Returns the icon associated with this node.
348   * @return the icon associated with this node.
349   */
350  public Icon getIcon() {
351    return icon;
352  }
353
354
355  /**
356   * Sets the icon associated with this node.
357   * @param icon the icon associated with this node.
358   */
359  public void setIcon(Icon icon) {
360    this.icon = icon;
361  }
362
363  /**
364   * Returns the font style to be used to render this node.
365   * @return the font style to be used to render this node.
366   */
367  public int getFontStyle() {
368    return fontStyle;
369  }
370
371  /**
372   * Sets the font style to be used to render this node.
373   * @param style the font style to be used to render this node.
374   */
375  public void setFontStyle(int style) {
376    fontStyle = style;
377  }
378
379
380  /**
381   * Returns the object class values associated with the entry.
382   * @return the object class values associated with the entry.
383   */
384  public String[] getObjectClassValues() {
385    return objectClassValues;
386  }
387
388  /**
389   * Sets the object class values associated with the entry.
390   * @param objectClassValues the object class values associated with the entry.
391   */
392  public void setObjectClassValues(String[] objectClassValues) {
393    this.objectClassValues = objectClassValues;
394  }
395
396  /**
397   * Extracts the RDN value from a DN.
398   * @param dn the DN.
399   * @param showAttributeName whether the result must include the attribute name
400   * or not.
401   * @return the RDN value from the DN.
402   */
403  public static String extractRDN(String dn, boolean showAttributeName) {
404    String result;
405    if (dn == null)
406    {
407      result = null;
408    }
409    else
410    {
411      try
412      {
413        DN dnObj = DN.valueOf(dn);
414        if (dnObj.size() >= 1) {
415          RDN rdn = dnObj.rdn();
416          if (showAttributeName)
417          {
418            result = rdn.toString();
419          }
420          else
421          {
422            result = rdn.getAttributeValue(0).toString();
423          }
424        }
425        else {
426          result = "";
427        }
428      }
429      catch (Throwable t)
430      {
431        throw new IllegalArgumentException(
432            "The provided argument is not a valid dn: "+t, t);
433      }
434    }
435    return result;
436  }
437
438  /**
439   * Extracts the RDN value from the DN.  The value does not include the name
440   * of the attribute.
441   * @param dn the DN.
442   * @return the RDN value from the DN.
443   */
444  public static String extractRDN(String dn) {
445    return extractRDN(dn, false);
446  }
447
448
449  /**
450   * Returns <CODE>true</CODE> if the size limit was reached updating this node
451   * (and searching its children) and <CODE>false</CODE> otherwise.
452   * @return <CODE>true</CODE> if the size limit was reached updating this node
453   * (and searching its children) and <CODE>false</CODE> otherwise.
454   */
455  public boolean isSizeLimitReached()
456  {
457    return sizeLimitReached;
458  }
459
460
461  /**
462   * Sets whether the size limit was reached updating this node
463   * (and searching its children).
464   * @param sizeLimitReached whether the size limit was reached updating this
465   * node (and searching its children).
466   */
467  public void setSizeLimitReached(boolean sizeLimitReached)
468  {
469    this.sizeLimitReached = sizeLimitReached;
470  }
471}