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.CmsObject; 031import org.opencms.file.CmsUser; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.ui.CmsVaadinUtils; 035import org.opencms.ui.components.CmsBasicDialog; 036import org.opencms.ui.components.editablegroup.CmsEditableGroup; 037import org.opencms.ui.components.editablegroup.I_CmsEditableGroupRow; 038import org.opencms.util.CmsDataTypeUtil; 039import org.opencms.util.CmsStringUtil; 040import org.opencms.util.CmsUUID; 041 042import java.util.ArrayList; 043import java.util.Collections; 044import java.util.Iterator; 045import java.util.List; 046import java.util.Map.Entry; 047import java.util.SortedMap; 048import java.util.TreeMap; 049 050import org.apache.commons.logging.Log; 051 052import com.google.common.base.Supplier; 053import com.vaadin.ui.Button; 054import com.vaadin.ui.Button.ClickEvent; 055import com.vaadin.ui.Button.ClickListener; 056import com.vaadin.ui.Component; 057import com.vaadin.ui.FormLayout; 058import com.vaadin.ui.Window; 059import com.vaadin.v7.ui.HorizontalLayout; 060import com.vaadin.v7.ui.TextField; 061 062/** 063 * Class for the Additional User info dialog.<p> 064 */ 065public class CmsAdditionalInfosDialog extends CmsBasicDialog { 066 067 /**vaadin serial id. */ 068 private static final long serialVersionUID = 9007206105761103873L; 069 070 /** The logger of this class. */ 071 private static final Log LOG = CmsLog.getLog(CmsAdditionalInfosDialog.class); 072 073 /**CmsUser to edit additional infos for. */ 074 private CmsUser m_user; 075 076 /**vaadin component.*/ 077 private FormLayout m_layout; 078 079 /**Layout for not editable info. */ 080 private FormLayout m_layoutnoedit; 081 082 /**cancel button.*/ 083 private Button m_cancel; 084 085 /**ok button.*/ 086 private Button m_ok; 087 088 /** The map of editable additional info entries. */ 089 private SortedMap<String, Object> m_addInfoEditable; 090 091 /** The map of non-editable additional info entries. */ 092 private SortedMap<String, Object> m_addInfoReadOnly; 093 094 /** The group for the module resource fields. */ 095 private CmsEditableGroup m_userinfoGroup; 096 097 /** The group for the module resource fields. */ 098 private CmsEditableGroup m_userinfoNoEditGroup; 099 100 /** CmsObject.*/ 101 private CmsObject m_cms; 102 103 /** 104 * public constructor.<p> 105 * 106 * @param cms CmsObject 107 * @param userID id of user 108 * @param window window 109 * @param app 110 */ 111 public CmsAdditionalInfosDialog(CmsObject cms, CmsUUID userID, final Window window, CmsAccountsApp app) { 112 113 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 114 115 m_cms = cms; 116 try { 117 m_user = cms.readUser(userID); 118 displayResourceInfoDirectly(Collections.singletonList(CmsAccountsApp.getPrincipalInfo(m_user))); 119 } catch (CmsException e) { 120 // 121 } 122 123 setAddInfoMaps(); 124 125 Supplier<Component> fieldFactory = new Supplier<Component>() { 126 127 public Component get() { 128 129 return addInfoLayout("", "", true); 130 } 131 }; 132 133 m_userinfoGroup = new CmsEditableGroup(m_layout, fieldFactory, "Add"); 134 m_userinfoGroup.init(); 135 136 m_userinfoNoEditGroup = new CmsEditableGroup(m_layoutnoedit, fieldFactory, "Add"); 137 m_userinfoNoEditGroup.setAddButtonVisible(false); 138 m_userinfoNoEditGroup.init(); 139 140 for (String info : m_addInfoEditable.keySet()) { 141 addAddInfoLayout(info, m_addInfoEditable.get(info), true); 142 } 143 144 for (String info : m_addInfoReadOnly.keySet()) { 145 addAddInfoLayout(info, m_addInfoReadOnly.get(info), false); 146 } 147 148 window.setCaption( 149 CmsVaadinUtils.getMessageText( 150 org.opencms.ui.apps.Messages.GUI_USERMANAGEMENT_USER_ADDITIONAL_INFOS_WINDOW_CAPTION_1, 151 m_user.getSimpleName())); 152 153 m_cancel.addClickListener(new ClickListener() { 154 155 private static final long serialVersionUID = 4879585408645749L; 156 157 public void buttonClick(ClickEvent event) { 158 159 window.close(); 160 } 161 162 }); 163 164 m_ok.addClickListener(new ClickListener() { 165 166 /**vaadin serial id. */ 167 private static final long serialVersionUID = -5168099515616397665L; 168 169 public void buttonClick(ClickEvent event) { 170 171 submit(); 172 window.close(); 173 app.reload(); 174 } 175 }); 176 177 } 178 179 /** 180 * Submit additional info to user.<p> 181 */ 182 protected void submit() { 183 184 if (m_userinfoNoEditGroup.getRows().size() != m_addInfoReadOnly.size()) { 185 List<String> currentKeys = getKeyListFromGroup(m_userinfoNoEditGroup); 186 for (String key : m_addInfoReadOnly.keySet()) { 187 if (!currentKeys.contains(key)) { 188 saveAddInfo(key, null); 189 } 190 } 191 } 192 193 for (I_CmsEditableGroupRow row : m_userinfoGroup.getRows()) { 194 String key = ((TextField)(((HorizontalLayout)row.getComponent()).getComponent(0))).getValue(); 195 String value = ((TextField)(((HorizontalLayout)row.getComponent()).getComponent(1))).getValue(); 196 saveAddInfo(key, value); 197 m_addInfoEditable.remove(key); 198 } 199 200 //Remaining items in list seem to be deleted by the user.. 201 for (String key : m_addInfoEditable.keySet()) { 202 saveAddInfo(key, null); 203 } 204 try { 205 m_cms.writeUser(m_user); 206 } catch (CmsException e) { 207 LOG.error("Unable to write user.", e); 208 } 209 } 210 211 /** 212 * Get horizontal layout with key, value from additional info.<p> 213 * 214 * @param key key 215 * @param value value 216 * @param editable boolean 217 * @return HorizontalLayout 218 */ 219 HorizontalLayout addInfoLayout(String key, Object value, boolean editable) { 220 221 HorizontalLayout res = new HorizontalLayout(); 222 res.setWidth("100%"); 223 res.setSpacing(true); 224 225 TextField keyField = new TextField(); 226 keyField.setValue(key); 227 keyField.setEnabled(editable); 228 keyField.setWidth("100%"); 229 230 TextField valueField = new TextField(); 231 valueField.setValue(value.toString()); 232 valueField.setEnabled(editable); 233 valueField.setWidth("100%"); 234 235 res.addComponent(keyField); 236 res.addComponent(valueField); 237 238 res.setExpandRatio(keyField, 1); 239 res.setExpandRatio(valueField, 1); 240 241 return res; 242 } 243 244 /** 245 * Add key value pair as component to ui.<p> 246 * 247 * @param key string 248 * @param value object 249 * @param editable boolean 250 */ 251 private void addAddInfoLayout(String key, Object value, boolean editable) { 252 253 HorizontalLayout res = addInfoLayout(key, value, editable); 254 if (editable) { 255 m_userinfoGroup.addRow(res); 256 } else { 257 m_userinfoNoEditGroup.addRow(res); 258 } 259 } 260 261 /** 262 * Get List of keys from UI.<p> 263 * 264 * @param group editablegroup object 265 * @return List of keys 266 */ 267 private List<String> getKeyListFromGroup(CmsEditableGroup group) { 268 269 List<String> res = new ArrayList<String>(); 270 for (I_CmsEditableGroupRow row : group.getRows()) { 271 res.add(((TextField)(((HorizontalLayout)row.getComponent()).getComponent(0))).getValue()); 272 } 273 return res; 274 } 275 276 /** 277 * Adds additional info to user.<p> 278 * (Doesn't write the user)<p> 279 * 280 * @param key string 281 * @param value string 282 */ 283 private void saveAddInfo(String key, String value) { 284 285 int pos = key.indexOf("@"); 286 287 String className = ""; 288 if (pos > -1) { 289 className = key.substring(pos + 1); 290 key = key.substring(0, pos); 291 } 292 293 if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) { 294 m_user.deleteAdditionalInfo(key); 295 return; 296 } 297 298 if (pos < 0) { 299 m_user.setAdditionalInfo(key, value); 300 return; 301 } 302 303 Class<?> clazz; 304 try { 305 // try the class name 306 clazz = Class.forName(className); 307 } catch (Throwable e) { 308 try { 309 // try the class in the java.lang package 310 clazz = Class.forName(Integer.class.getPackage().getName() + "." + className); 311 } catch (Throwable e1) { 312 clazz = String.class; 313 } 314 } 315 m_user.setAdditionalInfo(key, CmsDataTypeUtil.parse(value, clazz)); 316 } 317 318 /** 319 * Builds the additional info maps.<p> 320 */ 321 private void setAddInfoMaps() { 322 323 m_addInfoEditable = new TreeMap<String, Object>(); 324 m_addInfoReadOnly = new TreeMap<String, Object>(); 325 Iterator<Entry<String, Object>> itEntries = m_user.getAdditionalInfo().entrySet().iterator(); 326 while (itEntries.hasNext()) { 327 Entry<String, Object> entry = itEntries.next(); 328 String key = entry.getKey().toString(); 329 if ((entry.getValue() == null) || CmsStringUtil.isEmptyOrWhitespaceOnly(entry.getValue().toString())) { 330 // skip empty entries 331 continue; 332 } 333 if (!entry.getValue().getClass().equals(String.class)) { 334 // only show type different to string 335 key += "@" + entry.getValue().getClass().getName(); 336 } 337 if (CmsDataTypeUtil.isParseable(entry.getValue().getClass())) { 338 m_addInfoEditable.put(key, entry.getValue()); 339 } else { 340 String value = entry.getValue().toString(); 341 if (value.length() > (75 - key.length())) { 342 if ((75 - key.length()) > 5) { 343 value = value.substring(0, (75 - key.length())) + " ..."; 344 } else { 345 value = "..."; 346 } 347 } 348 m_addInfoReadOnly.put(key, value); 349 } 350 } 351 } 352}