001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ui.apps.user; 029 030import org.opencms.file.CmsGroup; 031import org.opencms.file.CmsObject; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.main.OpenCms; 035import org.opencms.security.CmsOrganizationalUnit; 036import org.opencms.security.CmsRole; 037import org.opencms.ui.A_CmsUI; 038import org.opencms.ui.CmsCssIcon; 039import org.opencms.ui.components.OpenCmsTheme; 040import org.opencms.util.CmsUUID; 041 042import java.util.ArrayList; 043import java.util.Collection; 044import java.util.List; 045 046import org.apache.commons.lang3.tuple.Pair; 047import org.apache.commons.logging.Log; 048 049import com.vaadin.v7.data.Item; 050import com.vaadin.v7.data.util.HierarchicalContainer; 051import com.vaadin.v7.event.ItemClickEvent; 052import com.vaadin.v7.event.ItemClickEvent.ItemClickListener; 053import com.vaadin.v7.ui.Tree; 054 055/** 056 * Class for the OU Tree.<p> 057 */ 058public class CmsOuTree extends Tree { 059 060 /** Log instance for this class. */ 061 private static final Log LOG = CmsLog.getLog(CmsOuTree.class); 062 063 /**Root OU.*/ 064 private static CmsOrganizationalUnit m_rootSystemOU; 065 066 /**name property. */ 067 private static final String PROP_NAME = "name"; 068 069 /**type property. */ 070 private static final String PROP_TYPE = "type"; 071 072 /**vaadin serial id.*/ 073 private static final long serialVersionUID = -3532367333216144806L; 074 075 private static final String PROP_SID = "sid"; 076 077 /**Calling app. */ 078 private CmsAccountsApp m_app; 079 080 /**CmsObject. */ 081 private CmsObject m_cms; 082 083 /**Root ou. */ 084 private CmsOrganizationalUnit m_rootOu; 085 086 /**Container. */ 087 private HierarchicalContainer m_treeContainer; 088 089 /** 090 * constructor.<p> 091 * 092 * @param cms CmsObject 093 * @param app app instance 094 * @param baseOU baseOu 095 */ 096 public CmsOuTree(CmsObject cms, CmsAccountsApp app, String baseOU) { 097 098 m_cms = cms; 099 try { 100 m_rootSystemOU = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, ""); 101 } catch (CmsException e1) { 102 // 103 } 104 m_app = app; 105 addStyleName(OpenCmsTheme.FULL_WIDTH_PADDING); 106 addStyleName(OpenCmsTheme.SIMPLE_DRAG); 107 setWidth("100%"); 108 m_treeContainer = new HierarchicalContainer(); 109 m_treeContainer.addContainerProperty(PROP_NAME, String.class, ""); 110 m_treeContainer.addContainerProperty(PROP_TYPE, I_CmsOuTreeType.class, null); 111 m_treeContainer.addContainerProperty(PROP_SID, CmsUUID.class, null); 112 setContainerDataSource(m_treeContainer); 113 114 m_rootOu = null; 115 try { 116 m_rootOu = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, baseOU); 117 Item item = m_treeContainer.addItem(m_rootOu); 118 item.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(m_rootOu, CmsOuTreeType.OU)); 119 item.getItemProperty(PROP_TYPE).setValue(CmsOuTreeType.OU); 120 } catch (CmsException e) { 121 LOG.error("Unable to read OU", e); 122 } 123 setItemCaptionPropertyId(PROP_NAME); 124 setHtmlContentAllowed(true); 125 setNullSelectionAllowed(false); 126 addChildrenForOUNode(m_rootOu); 127 expandItem(m_rootOu); 128 addItemClickListener(new ItemClickListener() { 129 130 private static final long serialVersionUID = -6475529853027436127L; 131 132 public void itemClick(ItemClickEvent event) { 133 134 handleItemClick(event.getItemId()); 135 136 } 137 }); 138 addExpandListener(new ExpandListener() { 139 140 private static final long serialVersionUID = 589297480547091120L; 141 142 public void nodeExpand(ExpandEvent event) { 143 144 handleExpand(event.getItemId()); 145 146 } 147 }); 148 } 149 150 /** 151 * Opens given path.<p> 152 * 153 * @param path ou path (=ou-name) 154 * @param type type (ou,group or user) 155 * @param groupID id of group (optional) 156 */ 157 public void openPath(String path, I_CmsOuTreeType type, CmsUUID groupID) { 158 159 if (type == null) { 160 return; 161 } 162 try { 163 expandItem(m_rootOu); 164 String[] pathP = path.split("/"); 165 String complPath = ""; 166 for (String subP : pathP) { 167 complPath += subP + "/"; 168 CmsOrganizationalUnit ou = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, complPath); 169 addChildrenForOUNode(ou); 170 expandItem(ou); 171 } 172 173 if (type.isGroup() || type.isRole()) { 174 String itemId = type.getId() 175 + OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, path).getName(); 176 expandItem(itemId); 177 if (groupID == null) { 178 setValue(itemId); 179 return; 180 } 181 setValue(groupID); 182 return; 183 } 184 if (type.isUser()) { 185 setValue(type.getId() + OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, path).getName()); 186 return; 187 } 188 189 setValue(OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, path)); 190 191 } catch (CmsException e) { 192 LOG.error("Unable to read OU", e); 193 } 194 } 195 196 /** 197 * Handle expand action.<p> 198 * 199 * @param itemId which was expended 200 */ 201 protected void handleExpand(Object itemId) { 202 203 I_CmsOuTreeType type = (I_CmsOuTreeType)getItem(itemId).getItemProperty(PROP_TYPE).getValue(); 204 loadAndExpand(itemId, type); 205 } 206 207 /** 208 * Handle item click.<p> 209 * 210 * @param itemId item which was clicked 211 */ 212 protected void handleItemClick(Object itemId) { 213 214 Item item = getItem(itemId); 215 I_CmsOuTreeType type = (I_CmsOuTreeType)getItem(itemId).getItemProperty(PROP_TYPE).getValue(); 216 CmsUUID roleOrGroupID = null; 217 boolean idInItem = false; 218 if (itemId instanceof CmsUUID) { 219 roleOrGroupID = (CmsUUID)itemId; 220 idInItem = true; 221 } else if (item.getItemProperty(PROP_SID).getValue() != null) { 222 roleOrGroupID = (CmsUUID)(item.getItemProperty(PROP_SID).getValue()); 223 idInItem = true; 224 } 225 if (type.equals(CmsOuTreeType.ROLE)) { 226 String ou = getOuFromItem(itemId, CmsOuTreeType.ROLE); 227 boolean isRoot = ou.isEmpty(); 228 if (isRoot) { 229 ou = "/"; 230 } 231 if (!((String)itemId).endsWith(ou)) { 232 if (isRoot) { 233 if (((String)itemId).length() > (ou.length() + 1)) { 234 roleOrGroupID = new CmsUUID(((String)itemId).substring(ou.length() + 1)); 235 } 236 } else { 237 roleOrGroupID = new CmsUUID(((String)itemId).substring(ou.length() + 2)); 238 } 239 } 240 } 241 242 m_app.update(getOuFromItem(itemId, type), type, roleOrGroupID, ""); 243 if (isExpanded(itemId) || idInItem) { 244 return; 245 } 246 loadAndExpand(itemId, type); 247 setValue(itemId); 248 249 } 250 251 /** 252 * Add groups for given group parent item. 253 * 254 * @param type the tree type 255 * @param ouItem group parent item 256 */ 257 private void addChildrenForGroupsNode(I_CmsOuTreeType type, String ouItem) { 258 259 try { 260 // Cut of type-specific prefix from ouItem with substring() 261 List<CmsGroup> groups = m_app.readGroupsForOu(m_cms, ouItem.substring(1), type, false); 262 for (CmsGroup group : groups) { 263 Pair<String, CmsUUID> key = Pair.of(type.getId(), group.getId()); 264 Item groupItem = m_treeContainer.addItem(key); 265 if (groupItem == null) { 266 groupItem = getItem(key); 267 } 268 groupItem.getItemProperty(PROP_SID).setValue(group.getId()); 269 groupItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(group, CmsOuTreeType.GROUP)); 270 groupItem.getItemProperty(PROP_TYPE).setValue(type); 271 setChildrenAllowed(key, false); 272 m_treeContainer.setParent(key, ouItem); 273 } 274 } catch (CmsException e) { 275 LOG.error("Can not read group", e); 276 } 277 } 278 279 /** 280 * Add children for ou.<p> 281 * 282 * @param item ou item 283 */ 284 private void addChildrenForOUNode(CmsOrganizationalUnit item) { 285 286 List<Object> itemsToRemove = new ArrayList<Object>(); 287 288 Collection<?> childCol = m_treeContainer.getChildren(item); 289 if (childCol != null) { 290 itemsToRemove.addAll(childCol); 291 } 292 293 try { 294 if (m_app.isOUManagable(item.getName())) { 295 296 List<I_CmsOuTreeType> types = m_app.getTreeTypeProvider().getTreeTypes(); 297 for (I_CmsOuTreeType type : types) { 298 if (!type.isValidForOu(m_cms, item.getName())) { 299 continue; 300 } 301 if (type.isOrgUnit()) { 302 continue; 303 } 304 String itemId = type.getId() + item.getName(); 305 Item newItem = m_treeContainer.addItem(itemId); 306 itemsToRemove.remove(itemId); 307 if (newItem != null) { 308 newItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(itemId, type)); 309 newItem.getItemProperty(PROP_TYPE).setValue(type); 310 m_treeContainer.setParent(itemId, item); 311 setChildrenAllowed(itemId, type.isExpandable()); 312 } 313 } 314 } 315 List<CmsOrganizationalUnit> ous = OpenCms.getOrgUnitManager().getOrganizationalUnits( 316 m_cms, 317 item.getName(), 318 false); 319 List<CmsOrganizationalUnit> webOus = new ArrayList<CmsOrganizationalUnit>(); 320 for (CmsOrganizationalUnit ou : ous) { 321 if (m_app.isParentOfManagableOU(ou.getName())) { 322 itemsToRemove.remove(ou); 323 if (ou.hasFlagWebuser()) { 324 webOus.add(ou); 325 } else { 326 addOuToTree(ou, item); 327 } 328 } 329 } 330 for (CmsOrganizationalUnit ou : webOus) { 331 if (m_app.isParentOfManagableOU(ou.getName())) { 332 itemsToRemove.remove(ou); 333 addOuToTree(ou, item); 334 } 335 } 336 } catch (CmsException e) { 337 LOG.error("Can't read ou", e); 338 } 339 for (Object it : itemsToRemove) { 340 m_treeContainer.removeItemRecursively(it); 341 } 342 } 343 344 /** 345 * Add roles for given role parent item. 346 * 347 * @param ouItem group parent item 348 */ 349 private void addChildrenForRolesNode(String ouItem) { 350 351 try { 352 List<CmsRole> roles = OpenCms.getRoleManager().getRoles(m_cms, ouItem.substring(1), false); 353 CmsRole.applySystemRoleOrder(roles); 354 for (CmsRole role : roles) { 355 String roleId = ouItem + "/" + role.getId(); 356 Item roleItem = m_treeContainer.addItem(roleId); 357 if (roleItem == null) { 358 roleItem = getItem(roleId); 359 } 360 roleItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(role, CmsOuTreeType.ROLE)); 361 roleItem.getItemProperty(PROP_TYPE).setValue(CmsOuTreeType.ROLE); 362 setChildrenAllowed(roleId, false); 363 m_treeContainer.setParent(roleId, ouItem); 364 } 365 } catch (CmsException e) { 366 LOG.error("Can not read group", e); 367 } 368 } 369 370 /** 371 * Adds an ou to the tree.<p> 372 * 373 * @param ou to be added 374 * @param parent_ou parent ou 375 */ 376 private void addOuToTree(CmsOrganizationalUnit ou, CmsOrganizationalUnit parent_ou) { 377 378 Item containerItem; 379 containerItem = m_treeContainer.addItem(ou); 380 if (containerItem == null) { 381 containerItem = getItem(ou); 382 } 383 containerItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(ou, CmsOuTreeType.OU)); 384 containerItem.getItemProperty(PROP_TYPE).setValue(CmsOuTreeType.OU); 385 m_treeContainer.setParent(ou, parent_ou); 386 } 387 388 /** 389 * Get HTML for icon and item caption.<p> 390 * 391 * @param item item to get icon and caption for 392 * @param type type 393 * @return html 394 */ 395 private String getIconCaptionHTML(Object item, I_CmsOuTreeType type) { 396 397 CmsCssIcon icon = type.getIcon(); 398 String caption = type.getName(); 399 if (item instanceof CmsOrganizationalUnit) { 400 CmsOrganizationalUnit ou = (CmsOrganizationalUnit)item; 401 if (ou.hasFlagWebuser()) { 402 icon = new CmsCssIcon(OpenCmsTheme.ICON_OU_WEB); 403 } 404 caption = (ou.equals(m_rootSystemOU) ? ou.getDisplayName(A_CmsUI.get().getLocale()) : ou.getName()); 405 } 406 407 if (item instanceof CmsGroup) { 408 //Real group shown under groups 409 caption = ((CmsGroup)item).getName(); 410 icon = m_app.getGroupIcon((CmsGroup)item); 411 } 412 413 if (item instanceof CmsRole) { 414 //Real group shown under groups 415 caption = ((CmsRole)item).getName(A_CmsUI.get().getLocale()); 416 } 417 418 if (icon != null) { 419 return "<span class=\"o-resource-icon\">" 420 + icon.getHtml() 421 + "</span>" 422 + "<span class=\"o-tree-caption\">" 423 + caption 424 + "</span>"; 425 } 426 return ""; 427 } 428 429 /** 430 * Gets ou from given item.<p> 431 * 432 * @param itemId to get ou for 433 * @param type of given item 434 * @return name of ou 435 */ 436 private String getOuFromItem(Object itemId, I_CmsOuTreeType type) { 437 438 if (type.equals(CmsOuTreeType.OU)) { 439 return ((CmsOrganizationalUnit)itemId).getName(); 440 } 441 Object o = m_treeContainer.getParent(itemId); 442 while (!(o instanceof CmsOrganizationalUnit)) { 443 o = m_treeContainer.getParent(o); 444 } 445 return ((CmsOrganizationalUnit)o).getName(); 446 } 447 448 /** 449 * Load and expand given item.<p> 450 * 451 * @param itemId to be expanded 452 * @param type of item 453 */ 454 private void loadAndExpand(Object itemId, I_CmsOuTreeType type) { 455 456 if (type.isOrgUnit()) { 457 addChildrenForOUNode((CmsOrganizationalUnit)itemId); 458 } 459 if (type.isGroup()) { 460 addChildrenForGroupsNode(type, (String)itemId); 461 } 462 if (type.isRole()) { 463 addChildrenForRolesNode((String)itemId); 464 } 465 expandItem(itemId); 466 } 467 468}