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