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-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017 018package org.opends.guitools.controlpanel.ui; 019 020import static org.opends.messages.AdminToolMessages.*; 021 022import java.awt.Component; 023import java.awt.Container; 024import java.awt.GridBagConstraints; 025import java.awt.event.KeyAdapter; 026import java.awt.event.KeyEvent; 027import java.awt.event.MouseAdapter; 028import java.awt.event.MouseEvent; 029import java.util.Comparator; 030import java.util.Set; 031import java.util.SortedSet; 032import java.util.TreeSet; 033 034import javax.swing.DefaultListModel; 035import javax.swing.JLabel; 036import javax.swing.JList; 037 038import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 039import org.opends.guitools.controlpanel.ui.components.TitlePanel; 040import org.opends.guitools.controlpanel.util.LowerCaseComparator; 041import org.opends.guitools.controlpanel.util.Utilities; 042import org.forgerock.i18n.LocalizableMessage; 043import org.forgerock.i18n.LocalizableMessageBuilder; 044import org.forgerock.opendj.ldap.schema.MatchingRule; 045import org.forgerock.opendj.ldap.schema.AttributeType; 046import org.opends.server.schema.SomeSchemaElement; 047import org.opends.server.types.ObjectClass; 048import org.opends.server.types.Schema; 049 050/** 051 * The panel that displays a standard attribute definition. 052 * 053 */ 054public class StandardAttributePanel extends SchemaElementPanel 055{ 056 private static final long serialVersionUID = -7922968631524763675L; 057 private TitlePanel titlePanel = new TitlePanel(LocalizableMessage.EMPTY, 058 LocalizableMessage.EMPTY); 059 private JLabel name = Utilities.createDefaultLabel(); 060 private JLabel parent = Utilities.createDefaultLabel(); 061 private JLabel oid = Utilities.createDefaultLabel(); 062 private JLabel aliases = Utilities.createDefaultLabel(); 063 private JLabel origin = Utilities.createDefaultLabel(); 064 private JLabel description = Utilities.createDefaultLabel(); 065 private JLabel usage = Utilities.createDefaultLabel(); 066 private JLabel syntax = Utilities.createDefaultLabel(); 067 private JLabel approximate = Utilities.createDefaultLabel(); 068 private JLabel equality = Utilities.createDefaultLabel(); 069 private JLabel ordering = Utilities.createDefaultLabel(); 070 private JLabel substring = Utilities.createDefaultLabel(); 071 private JLabel type = Utilities.createDefaultLabel(); 072 private JList requiredBy = new JList(new DefaultListModel()); 073 private JList optionalBy = new JList(new DefaultListModel()); 074 075 /** 076 * Default constructor of the panel. 077 * 078 */ 079 public StandardAttributePanel() 080 { 081 super(); 082 createLayout(); 083 } 084 085 /** {@inheritDoc} */ 086 public LocalizableMessage getTitle() 087 { 088 return INFO_CTRL_PANEL_STANDARD_ATTRIBUTE_TITLE.get(); 089 } 090 091 /** {@inheritDoc} */ 092 public Component getPreferredFocusComponent() 093 { 094 return requiredBy; 095 } 096 097 /** {@inheritDoc} */ 098 public void configurationChanged(ConfigurationChangeEvent ev) 099 { 100 } 101 102 /** {@inheritDoc} */ 103 public void okClicked() 104 { 105 } 106 107 /** 108 * Creates the layout of the panel (but the contents are not populated here). 109 */ 110 protected void createLayout() 111 { 112 createBasicLayout(this, new GridBagConstraints()); 113 setBorder(PANEL_BORDER); 114 } 115 116 /** 117 * Creates the basic layout of the panel. 118 * @param c the container where all the components will be layed out. 119 * @param gbc the grid bag constraints. 120 */ 121 protected void createBasicLayout(Container c, GridBagConstraints gbc) 122 { 123 requiredBy.setVisibleRowCount(5); 124 optionalBy.setVisibleRowCount(9); 125 126 gbc.gridy = 0; 127 gbc.gridwidth = 2; 128 addErrorPane(c, gbc); 129 gbc.gridy ++; 130 131 gbc.anchor = GridBagConstraints.WEST; 132 titlePanel.setTitle(INFO_CTRL_PANEL_ATTRIBUTE_DETAILS.get()); 133 gbc.fill = GridBagConstraints.NONE; 134 gbc.insets.top = 5; 135 gbc.insets.bottom = 7; 136 c.add(titlePanel, gbc); 137 138 gbc.insets.bottom = 0; 139 gbc.insets.top = 8; 140 gbc.gridy ++; 141 gbc.gridwidth = 1; 142 gbc.fill = GridBagConstraints.HORIZONTAL; 143 144 LocalizableMessage[] labels = { 145 INFO_CTRL_PANEL_ATTRIBUTE_NAME_LABEL.get(), 146 INFO_CTRL_PANEL_ATTRIBUTE_PARENT_LABEL.get(), 147 INFO_CTRL_PANEL_ATTRIBUTE_OID_LABEL.get(), 148 INFO_CTRL_PANEL_ATTRIBUTE_ALIASES_LABEL.get(), 149 INFO_CTRL_PANEL_ATTRIBUTE_ORIGIN_LABEL.get(), 150 INFO_CTRL_PANEL_ATTRIBUTE_DESCRIPTION_LABEL.get(), 151 INFO_CTRL_PANEL_ATTRIBUTE_USAGE_LABEL.get(), 152 INFO_CTRL_PANEL_ATTRIBUTE_SYNTAX_LABEL.get(), 153 INFO_CTRL_PANEL_ATTRIBUTE_TYPE_LABEL.get(), 154 INFO_CTRL_PANEL_ATTRIBUTE_APPROXIMATE_MATCHING_RULE_LABEL.get(), 155 INFO_CTRL_PANEL_ATTRIBUTE_EQUALITY_MATCHING_RULE_LABEL.get(), 156 INFO_CTRL_PANEL_ATTRIBUTE_ORDERING_MATCHING_RULE_LABEL.get(), 157 INFO_CTRL_PANEL_ATTRIBUTE_SUBSTRING_MATCHING_RULE_LABEL.get() 158 }; 159 JLabel[] values = {name, parent, oid, aliases, origin, description, usage, 160 syntax, type, approximate, equality, ordering, substring}; 161 162 for (int i=0; i < labels.length; i++) 163 { 164 gbc.insets.left = 0; 165 gbc.gridx = 0; 166 JLabel l = Utilities.createPrimaryLabel(labels[i]); 167 c.add(l, gbc); 168 gbc.insets.left = 10; 169 gbc.gridx = 1; 170 c.add(values[i], gbc); 171 gbc.gridy ++; 172 } 173 labels = new LocalizableMessage[] { 174 INFO_CTRL_PANEL_REQUIRED_BY_LABEL.get(), 175 INFO_CTRL_PANEL_ALLOWED_BY_LABEL.get() 176 }; 177 JList[] lists = {requiredBy, optionalBy}; 178 gbc.anchor = GridBagConstraints.NORTHWEST; 179 for (int i=0; i<2; i++) 180 { 181 gbc.insets.left = 0; 182 gbc.gridx = 0; 183 JLabel l = Utilities.createPrimaryLabel(labels[i]); 184 gbc.weightx = 0.0; 185 gbc.fill = GridBagConstraints.HORIZONTAL; 186 c.add(l, gbc); 187 gbc.insets.left = 10; 188 gbc.gridx = 1; 189 if (i == 0) 190 { 191 gbc.weighty = 0.35; 192 } 193 else 194 { 195 gbc.weighty = 0.65; 196 } 197 gbc.weightx = 1.0; 198 gbc.fill = GridBagConstraints.BOTH; 199 gbc.insets.top = 10; 200 c.add(Utilities.createScrollPane(lists[i]), gbc); 201 gbc.gridy ++; 202 203 final JList list = lists[i]; 204 MouseAdapter clickListener = new MouseAdapter() 205 { 206 /** {@inheritDoc} */ 207 public void mouseClicked(MouseEvent ev) 208 { 209 if (ev.getClickCount() == 1) 210 { 211 objectClassSelected(list); 212 } 213 } 214 }; 215 list.addMouseListener(clickListener); 216 217 KeyAdapter keyListener = new KeyAdapter() 218 { 219 /** {@inheritDoc} */ 220 public void keyTyped(KeyEvent ev) 221 { 222 if (ev.getKeyChar() == KeyEvent.VK_SPACE || 223 ev.getKeyChar() == KeyEvent.VK_ENTER) 224 { 225 objectClassSelected(list); 226 } 227 } 228 }; 229 list.addKeyListener(keyListener); 230 } 231 } 232 233 /** 234 * Updates the contents of the panel with the provided attribute. 235 * @param attr the attribute. 236 * @param schema the schema. 237 */ 238 public void update(AttributeType attr, Schema schema) 239 { 240 String n = attr.getNameOrOID(); 241 titlePanel.setDetails(LocalizableMessage.raw(n)); 242 name.setText(n); 243 AttributeType superior = attr.getSuperiorType(); 244 if (superior == null) 245 { 246 n = null; 247 } 248 else 249 { 250 n = superior.getNameOrOID(); 251 } 252 parent.setText(n); 253 oid.setText(attr.getOID()); 254 origin.setText(StandardObjectClassPanel.getOrigin(new SomeSchemaElement(attr)).toString()); 255 n = attr.getDescription(); 256 if (n == null) 257 { 258 n = NOT_APPLICABLE.toString(); 259 } 260 description.setText(n); 261 if (attr.getUsage() == null) 262 { 263 n = NOT_APPLICABLE.toString(); 264 } 265 else 266 { 267 n = attr.getUsage().toString(); 268 } 269 usage.setText(n); 270 Set<String> aliases = getAliases(attr); 271 if (!aliases.isEmpty()) 272 { 273 n = Utilities.getStringFromCollection(aliases, ", "); 274 } 275 else 276 { 277 n = NOT_APPLICABLE.toString(); 278 } 279 this.aliases.setText(n); 280 syntax.setText(Utilities.getSyntaxText(attr.getSyntax())); 281 JLabel[] labels = {approximate, equality, ordering, substring}; 282 MatchingRule[] rules = {attr.getApproximateMatchingRule(), 283 attr.getEqualityMatchingRule(), attr.getOrderingMatchingRule(), 284 attr.getSubstringMatchingRule() 285 }; 286 for (int i=0; i<labels.length; i++) 287 { 288 if (rules[i] != null) 289 { 290 labels[i].setText(Utilities.getMatchingRuleText(rules[i])); 291 } 292 else 293 { 294 labels[i].setText(NOT_APPLICABLE.toString()); 295 } 296 } 297 298 type.setText(getTypeValue(attr).toString()); 299 300 Comparator<String> lowerCaseComparator = new LowerCaseComparator(); 301 SortedSet<String> requiredByOcs = new TreeSet<>(lowerCaseComparator); 302 for (ObjectClass oc : schema.getObjectClasses().values()) 303 { 304 if (oc.getRequiredAttributeChain().contains(attr)) 305 { 306 requiredByOcs.add(oc.getNameOrOID()); 307 } 308 } 309 310 DefaultListModel model = (DefaultListModel)requiredBy.getModel(); 311 model.clear(); 312 for (String oc : requiredByOcs) 313 { 314 model.addElement(oc); 315 } 316 317 SortedSet<String> optionalByOcs = new TreeSet<>(lowerCaseComparator); 318 for (ObjectClass oc : schema.getObjectClasses().values()) 319 { 320 if (oc.getOptionalAttributeChain().contains(attr)) 321 { 322 optionalByOcs.add(oc.getNameOrOID()); 323 } 324 } 325 326 model = (DefaultListModel)optionalBy.getModel(); 327 model.clear(); 328 for (String oc : optionalByOcs) 329 { 330 model.addElement(oc); 331 } 332 } 333 334 /** 335 * Returns the message describing the attribute type (operational, single 336 * valued, etc.). 337 * @param attr the attribute. 338 * @return the message describing the attribute type (operational, single 339 * valued, etc.). 340 */ 341 static LocalizableMessage getTypeValue(AttributeType attr) 342 { 343 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 344 Boolean[] props = {attr.isOperational(), attr.isSingleValue(), 345 attr.isNoUserModification(), attr.isCollective(), 346 attr.isObsolete()}; 347 LocalizableMessage[][] values = { 348 {INFO_CTRL_PANEL_ATTRIBUTE_OPERATIONAL_LABEL.get(), null}, 349 {INFO_CTRL_PANEL_ATTRIBUTE_SINGLE_VALUED_LABEL.get(), 350 INFO_CTRL_PANEL_ATTRIBUTE_MULTI_VALUED_LABEL.get()}, 351 {INFO_CTRL_PANEL_ATTRIBUTE_NON_MODIFIABLE_LABEL.get(), null}, 352 {INFO_CTRL_PANEL_ATTRIBUTE_COLLECTIVE_LABEL.get(), null}, 353 {INFO_CTRL_PANEL_ATTRIBUTE_OBSOLETE_LABEL.get(), null}}; 354 int i = 0; 355 for (Boolean prop : props) 356 { 357 LocalizableMessage value = prop ? values[i][0] : values[i][1]; 358 if (value != null) 359 { 360 if (mb.length() > 0) 361 { 362 mb.append(", "); 363 } 364 mb.append(value); 365 } 366 i++; 367 } 368 return mb.toMessage(); 369 } 370}