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