001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.ui.ribbonconfiguration; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.UUID; 021 022import org.apache.avalon.framework.configuration.Configuration; 023import org.apache.avalon.framework.configuration.ConfigurationException; 024import org.apache.avalon.framework.configuration.DefaultConfiguration; 025import org.apache.cocoon.xml.AttributesImpl; 026import org.apache.cocoon.xml.XMLUtils; 027import org.slf4j.Logger; 028import org.xml.sax.ContentHandler; 029import org.xml.sax.SAXException; 030 031import org.ametys.core.ui.RibbonManager; 032import org.ametys.core.ui.RibbonTabsManager; 033import org.ametys.runtime.i18n.I18nizableText; 034 035/** 036 * A tab of the ribbon 037 */ 038public class Tab 039{ 040 /** The label of the tab */ 041 protected I18nizableText _label; 042 043 /** The optional id of the contextual client side element determining the state of the ribbon */ 044 protected String _controlId; 045 046 /** The color (between 1 and 6) for a contextual tab */ 047 protected String _contextualColor; 048 049 /** The id of the contextual group (can be null for single contextual tab) */ 050 protected String _contextualGroup; 051 052 /** The tab order */ 053 protected Object _order; 054 055 /** True to order before a tab specified by _order */ 056 protected Boolean _orderBefore; 057 058 /** True to override an existing tab instead of defining a new one */ 059 protected Boolean _override; 060 061 /** The list of groups in the tab */ 062 protected List<Group> _groups = new ArrayList<>(); 063 064 /** helper for group injection */ 065 protected RibbonElementsInjectionHelper<Group> _tabOverrideHelper; 066 067 /** Logger */ 068 protected Logger _log; 069 070 /** 071 * Creates a tab 072 * @param tabConfiguration The configuration of the tab 073 * @param ribbonManager The ribbon manager 074 * @param defaultOrder The default tab order, if not specified. Can be null 075 * @param logger The logger 076 * @throws ConfigurationException if an error occurs in the configuration 077 */ 078 public Tab(Configuration tabConfiguration, RibbonManager ribbonManager, Integer defaultOrder, Logger logger) throws ConfigurationException 079 { 080 _log = logger; 081 082 if (_log.isDebugEnabled()) 083 { 084 _log.debug("Creating tab"); 085 } 086 087 _configureId(tabConfiguration); 088 if (tabConfiguration.getAttribute("ref-id", null) != null || tabConfiguration.getChild("tab-control", false) != null) 089 { 090 _generateTabControl(tabConfiguration, ribbonManager); 091 } 092 093 this._label = new I18nizableText("application", tabConfiguration.getAttribute("label")); 094 if (_log.isDebugEnabled()) 095 { 096 _log.debug("Tab label is " + this._label); 097 } 098 099 this._override = tabConfiguration.getAttributeAsBoolean("override", false); 100 101 _configureGroups(tabConfiguration, ribbonManager); 102 _configureOrder(tabConfiguration, defaultOrder); 103 } 104 105 /** 106 * Get the id of this tab; 107 * @return the id 108 */ 109 public String getId() 110 { 111 return _controlId; 112 } 113 114 /** 115 * Return true if the tab is contextual 116 * @return true if the tab is contextual 117 */ 118 public Boolean isContextual() 119 { 120 return _controlId != null; 121 } 122 123 /** 124 * Configure tab optional id 125 * @param tabConfiguration One tab configuration 126 * @throws ConfigurationException if an error occurred 127 */ 128 protected void _configureId(Configuration tabConfiguration) throws ConfigurationException 129 { 130 this._controlId = tabConfiguration.getAttribute("controlId", null); 131 this._contextualColor = tabConfiguration.getAttribute("contextualColor", null); 132 this._contextualGroup = tabConfiguration.getAttribute("contextualGroup", null); 133 134 if (_log.isDebugEnabled() && this._controlId != null) 135 { 136 _log.debug("Tab control id is " + this._controlId); 137 } 138 } 139 140 /** 141 * Generate a new tab control on the fly 142 * @param tabConfiguration The tab configuration 143 * @param ribbonManager The ribbon manager 144 * @throws ConfigurationException If an error occurs 145 */ 146 protected void _generateTabControl(Configuration tabConfiguration, RibbonManager ribbonManager) throws ConfigurationException 147 { 148 if (this._controlId == null) 149 { 150 this._controlId = UUID.randomUUID().toString(); 151 } 152 153 DefaultConfiguration defaultConfig = new DefaultConfiguration(tabConfiguration.getChild("tab-control")); 154 String refId = defaultConfig.getAttribute("ref-id", null); 155 156 String classname = tabConfiguration.getAttribute("class", null); 157 if (classname == null) 158 { 159 if (refId != null) 160 { 161 defaultConfig.setAttribute("point", tabConfiguration.getAttribute("point", RibbonTabsManager.ROLE)); 162 } 163 else 164 { 165 classname = org.ametys.core.ui.StaticClientSideElement.class.getName(); 166 defaultConfig.setAttribute("class", classname); 167 } 168 } 169 170 ribbonManager.addExtension(this._controlId, "core-ui", null, defaultConfig); 171 172 if (_log.isDebugEnabled()) 173 { 174 _log.debug("Generated Tab control id is " + this._controlId); 175 } 176 } 177 178 /** 179 * Configure tabs groups 180 * @param tabConfiguration One tab configuration 181 * @param ribbonManager The ribbon manager 182 * @throws ConfigurationException if an error occurred 183 */ 184 protected void _configureGroups(Configuration tabConfiguration, RibbonManager ribbonManager) throws ConfigurationException 185 { 186 Configuration[] groupsConfigurations = tabConfiguration.getChild("groups").getChildren("group"); 187 for (Configuration groupConfiguration : groupsConfigurations) 188 { 189 Group group = new Group(groupConfiguration, ribbonManager, _log); 190 _groups.add(group); 191 } 192 } 193 194 private void _configureOrder(Configuration tabConfiguration, Integer defaultOrder) 195 { 196 String order = tabConfiguration.getAttribute("order", null); 197 try 198 { 199 _order = Integer.parseInt(order); 200 } 201 catch (NumberFormatException e) 202 { 203 _order = order != null ? order : defaultOrder; 204 } 205 206 _orderBefore = tabConfiguration.getAttributeAsBoolean("order-before", false); 207 } 208 209 /** 210 * Get the tab label 211 * @return Return the tab label 212 */ 213 public String getLabel() 214 { 215 return _label.toString(); 216 } 217 218 /** 219 * Get the order attribute of the tab 220 * @return Return the order as a String, or null 221 */ 222 public String getOrderAsString() 223 { 224 if (_order instanceof String) 225 { 226 return (String) _order; 227 } 228 return null; 229 } 230 231 /** 232 * Get the order attribute of the tab 233 * @return Return the order as an Integer, or null 234 */ 235 public Integer getOrderAsInteger() 236 { 237 if (_order instanceof Integer) 238 { 239 return (Integer) _order; 240 } 241 return null; 242 } 243 244 /** 245 * Set the order attribute of the tab 246 * @param order The new order value, either a String or an Integer 247 */ 248 public void setOrder(Object order) 249 { 250 _order = order; 251 } 252 253 /** 254 * True if the tab should be ordered before the tab referenced by the attribute order 255 * @return True if the tab should be ordered before the tab referenced by the attribute order 256 */ 257 public boolean orderBefore() 258 { 259 return _orderBefore; 260 } 261 262 /** 263 * Retrieve the list of configured groups 264 * @return The list of groups 265 */ 266 public List<Group> getGroups() 267 { 268 return _groups; 269 } 270 271 /** 272 * Return true if this tab overrides an existing tab 273 * @return True if overrides 274 */ 275 public boolean isOverride() 276 { 277 return _override; 278 } 279 280 /** 281 * Inject a list of groups into this tab 282 * @param groups The list of groups to inject 283 */ 284 public void injectGroups(List<Group> groups) 285 { 286 for (Group group : groups) 287 { 288 if (!group.isOverride()) 289 { 290 if (_tabOverrideHelper == null) 291 { 292 _tabOverrideHelper = new RibbonElementsInjectionHelper<>(_groups, _log); 293 } 294 295 if (_log.isDebugEnabled()) 296 { 297 _log.debug("RibbonConfigurationManager : new group '" + group._label.toString() + "' injected into tab '" + _label.toString() + "'"); 298 } 299 300 _tabOverrideHelper.injectElements(group, group.getOrder()); 301 } 302 } 303 } 304 305 /** 306 * Inject a list of overriding groups into this tab 307 * @param groups The list of groups to inject 308 */ 309 public void injectGroupsOverride(List<Group> groups) 310 { 311 for (Group group : groups) 312 { 313 if (group.isOverride()) 314 { 315 for (Group selfGroup : _groups) 316 { 317 if (selfGroup._label.equals(group._label)) 318 { 319 if (_log.isDebugEnabled()) 320 { 321 _log.debug("RibbonConfigurationManager : overriding group '" + group._label + "' of tab '" + _label + "' to inject new controls"); 322 } 323 324 selfGroup.injectGroup(group); 325 } 326 } 327 } 328 } 329 } 330 331 /** 332 * Sax the configuration of the tab. 333 * @param handler The content handler where to sax 334 * @param groups The list of groups to sax 335 * @throws SAXException if an error occurs 336 */ 337 public void saxGroups(ContentHandler handler, List<Group> groups) throws SAXException 338 { 339 AttributesImpl attrs = new AttributesImpl(); 340 attrs.addCDATAAttribute("label", _label.getCatalogue() + ":" + _label.getKey()); 341 StringBuilder i18nAttr = new StringBuilder("label"); 342 343 if (_controlId != null) 344 { 345 attrs.addCDATAAttribute("controlId", _controlId); 346 if (_contextualColor != null) 347 { 348 attrs.addCDATAAttribute("contextualColor", _contextualColor); 349 } 350 if (_contextualGroup != null) 351 { 352 attrs.addCDATAAttribute("contextualGroup", _contextualGroup); 353 } 354 } 355 356 attrs.addCDATAAttribute("http://apache.org/cocoon/i18n/2.1", "attr", "i18n:attr", i18nAttr.toString()); 357 358 XMLUtils.startElement(handler, "tab", attrs); 359 360 XMLUtils.startElement(handler, "groups"); 361 for (Group group : groups) 362 { 363 group.toSAX(handler); 364 } 365 XMLUtils.endElement(handler, "groups"); 366 367 XMLUtils.endElement(handler, "tab"); 368 } 369 370 @Override 371 public String toString() 372 { 373 return super.toString() + "[" + _label + "]"; 374 } 375}