Java tutorial
/** * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at license/ESCIDOC.LICENSE * or https://www.escidoc.org/license/ESCIDOC.LICENSE . * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at license/ESCIDOC.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * * Copyright 2012 Fachinformationszentrum Karlsruhe Gesellschaft * fuer wissenschaftlich-technische Information mbH and Max-Planck- * Gesellschaft zur Foerderung der Wissenschaft e.V. * All rights reserved. Use is subject to license terms. */ package org.escidoc.browser.ui; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import org.escidoc.browser.model.PropertyId; import org.escidoc.browser.model.ResourceModel; import org.escidoc.browser.model.ResourceType; import org.escidoc.browser.repository.Repositories; import org.escidoc.browser.repository.RoleRepository.RoleModel; import org.escidoc.browser.ui.role.OnRoleSelect; import org.escidoc.browser.ui.useraccount.UserRolesView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.util.BeanItem; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.terminal.ThemeResource; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Component; import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.NativeSelect; import com.vaadin.ui.Panel; import com.vaadin.ui.PopupView; import com.vaadin.ui.PopupView.PopupVisibilityEvent; import com.vaadin.ui.PopupView.PopupVisibilityListener; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.Window.Notification; import de.escidoc.core.client.exceptions.EscidocClientException; import de.escidoc.core.resources.aa.role.ScopeDef; import de.escidoc.core.resources.aa.useraccount.Grant; import de.escidoc.core.resources.common.reference.Reference; @SuppressWarnings("serial") public class GroupRolesView extends Panel { private final static Logger LOG = LoggerFactory.getLogger(UserRolesView.class); private final ComponentContainer rolesLayout = new VerticalLayout(); private final String groupId; private final Repositories repositories; private final Router router; // TODO CRUD View for User's Roles. // TODO View Layout: roleName | scopedOnResourceType | resourceName (resourceId) | removeBtn <-- row layout // TODO duplicate code for assigning grant and updating/showing grant // TODO Update: Edit existing role for the selected user. Change Role, Scope, Resource, etc // TODO PDP request??? public GroupRolesView(String groupId, Repositories repositories, Router router) throws EscidocClientException { this.groupId = groupId; this.repositories = repositories; this.router = router; init(); } private void init() throws EscidocClientException { setCaption("Roles Panel"); VerticalLayout vl = new VerticalLayout(); VerticalLayout excludeRoles = addRoleExcludeInformation(); vl.addComponent(excludeRoles); vl.addComponent(rolesLayout); setContent(vl); listRolesForUser(rolesLayout); } private VerticalLayout addRoleExcludeInformation() { VerticalLayout rlexclude = new VerticalLayout(); final Label content = new Label("<ul><li>The following Roles have been excluded from this view: <br />" + ViewConstants.roleExcludeList.toString() + "</li></ul>", Label.CONTENT_RAW); content.setWidth("300px"); final PopupView popup = new PopupView("?", content); popup.setHideOnMouseOut(true); popup.addListener(new PopupVisibilityListener() { @Override public void popupVisibilityChange(PopupVisibilityEvent event) { } }); popup.addStyleName("paddingright10"); rlexclude.addComponent(popup); rlexclude.setComponentAlignment(popup, Alignment.MIDDLE_RIGHT); rlexclude.setMargin(true); return rlexclude; } private void listRolesForUser(ComponentContainer grantListLayout) { grantListLayout.removeAllComponents(); try { if (repositories.group().getGrantsForGroup(groupId).size() == 0) { grantListLayout.addComponent(new Label("<h2>The group has no roles.</h2>", Label.CONTENT_XHTML)); } else { showExistingGrants(grantListLayout); } } catch (EscidocClientException e) { LOG.error("Cannot get grants for Group " + groupId + e.getLocalizedMessage() + "while showing Group " + groupId); } catch (Exception finalexception) { router.getMainWindow().showNotification("Fatal error!", "There has been a problem with this view. The Grants could not be retrieved saving them would attempt to overwrite the old ones. Please proceed with care <br />" + finalexception.getMessage(), Notification.TYPE_TRAY_NOTIFICATION); LOG.error("Final Exception" + finalexception.getLocalizedMessage()); } grantListLayout.addComponent(buildGrantRowAddView()); } private void showExistingGrants(ComponentContainer grantListLayout) throws EscidocClientException { int rowNumber = 0; for (Grant grant : repositories.group().getGrantsForGroup(groupId)) { /** * Some grants have been excluded from output because of performance issues. The list is found at: * ViewConstants.roleExcludeList */ if (!ViewConstants.roleExcludeList.contains(grant.getXLinkTitle().toString() .substring(0, grant.getXLinkTitle().toString().lastIndexOf(" of")).trim())) { HorizontalLayout existingGrantRowLayout = buildEditGrantRowView(rowNumber, grant); existingGrantRowLayout.setData(Integer.valueOf(rowNumber)); rowNumber++; bind(existingGrantRowLayout, grant); grantListLayout.addComponent(existingGrantRowLayout); } } } public String millisToShortDHMS(long duration) { String res = ""; long days = TimeUnit.MILLISECONDS.toDays(duration); long hours = TimeUnit.MILLISECONDS.toHours(duration) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration)); long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration)); long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)); if (days == 0) { res = String.format("%02d:%02d:%02d", hours, minutes, seconds); } else { res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds); } return res; } private Component buildGrantRowAddView() { HorizontalLayout addGrantRow = newRowGrantLayout(); final NativeSelect resourceTypeSelect = buildResourceTypeSelect(); final NativeSelect resourceSelect = buildResourceSelect(resourceTypeSelect); final NativeSelect roleNameSelect = buildRoleNameSelect(resourceTypeSelect, resourceSelect); addGrantRow.addComponent(roleNameSelect); addGrantRow.addComponent(resourceTypeSelect); addGrantRow.addComponent(resourceSelect); final Button saveButton = buildAddGrantButton(resourceSelect, roleNameSelect); addGrantRow.addComponent(saveButton); try { bindRoleName(roleNameSelect); } catch (EscidocClientException e) { router.getMainWindow().showNotification("Could not bind role-names"); LOG.error("Could not bind role-names" + e.getLocalizedMessage()); e.printStackTrace(); } return addGrantRow; } private HorizontalLayout buildEditGrantRowView(int rowNumber, Grant grant) { HorizontalLayout editGrantRow = newRowGrantLayout(); NativeSelect resourceTypeSelect = buildResourceTypeSelect(); NativeSelect resourceSelect = buildResourceSelect(resourceTypeSelect); NativeSelect roleNameSelect = buildRoleNameSelect(resourceTypeSelect, resourceSelect); editGrantRow.addComponent(roleNameSelect); editGrantRow.addComponent(resourceTypeSelect); editGrantRow.addComponent(resourceSelect); Button removeButton = buildRemoveButton(rowNumber, grant); editGrantRow.addComponent(removeButton); return editGrantRow; } private NativeSelect buildResourceSelect(NativeSelect resouceTypeSelect) { final NativeSelect resourceSelect = buildResourceSelect(); resouceTypeSelect.addListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { if (event.getProperty().getValue() instanceof ResourceType) { try { bind(resourceSelect, loadData((ResourceType) event.getProperty().getValue())); } catch (UnsupportedOperationException e) { router.getMainWindow().showNotification(ViewConstants.ERROR + "Unsupported Operation", e.getMessage(), Window.Notification.TYPE_ERROR_MESSAGE); } catch (EscidocClientException e) { router.getMainWindow().showNotification(ViewConstants.ERROR, e.getMessage(), Window.Notification.TYPE_ERROR_MESSAGE); } } } private void bind(NativeSelect resourceSelect, BeanItemContainer<ResourceModel> dataSource) { resourceSelect.setContainerDataSource(dataSource); resourceSelect.setItemCaptionPropertyId(PropertyId.NAME); } private BeanItemContainer<ResourceModel> loadData(ResourceType selectedType) throws EscidocClientException { final BeanItemContainer<ResourceModel> dataSource = newContainer(); for (final ResourceModel rm : findAll(selectedType)) { dataSource.addItem(rm); } return dataSource; } private List<ResourceModel> findAll(ResourceType type) throws EscidocClientException { List<ResourceModel> list = repositories.findByType(type).findAll(); Collections.sort(list, new Comparator<ResourceModel>() { @Override public int compare(ResourceModel o1, ResourceModel o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); return list; } }); return resourceSelect; } private static NativeSelect buildResourceTypeSelect() { final NativeSelect resourceTypeSelect = buildResourceSelect(); resourceTypeSelect.setWidth("100px"); return resourceTypeSelect; } private Button buildAddGrantButton(final NativeSelect resourceSelect, final NativeSelect roleNameSelect) { Button assignGrantButton = new Button(); assignGrantButton.setIcon(new ThemeResource("images/assets/plus.png")); assignGrantButton.addListener(new Button.ClickListener() { @Override public void buttonClick(@SuppressWarnings("unused") ClickEvent event) { try { if (getSelectedRole() == null) { router.getMainWindow().showNotification("Role can not be empty", "", Window.Notification.TYPE_WARNING_MESSAGE); return; } Grant grant = assignGrantInServer(); updateView(); showSuccessMessage(grant); } catch (EscidocClientException e) { router.getMainWindow().showNotification("Error Message", "Something wrong happens. Cause: " + e.getMessage(), Notification.TYPE_ERROR_MESSAGE); } } private void showSuccessMessage(Grant grant) { router.getMainWindow().showNotification("", "Sucessfully assign" + grant.getXLinkTitle() + " to " + groupId, Notification.TYPE_TRAY_NOTIFICATION); } private Grant assignGrantInServer() throws EscidocClientException { return repositories.group().assign(groupId).withRole(getSelectedRole()) .onResources(getSelectedResources()).execute(); } private RoleModel getSelectedRole() { final Object value = roleNameSelect.getValue(); if (value instanceof RoleModel) { return (RoleModel) value; } return null; } private Set<ResourceModel> getSelectedResources() { final Object value = resourceSelect.getValue(); if (value instanceof ResourceModel) { return Collections.singleton((ResourceModel) value); } return Collections.emptySet(); } private void updateView() throws EscidocClientException { listRolesForUser(rolesLayout); } }); return assignGrantButton; } private void bindRoleName(NativeSelect roleNameSelect) throws EscidocClientException { roleNameSelect.setContainerDataSource(buildRoleNameDataSource()); roleNameSelect.setItemCaptionPropertyId(PropertyId.NAME); } private static HorizontalLayout newRowGrantLayout() { HorizontalLayout grantLayout = new HorizontalLayout(); grantLayout.setSpacing(true); grantLayout.setMargin(true, false, false, false); return grantLayout; } private static NativeSelect buildResourceSelect() { NativeSelect select = new NativeSelect(); select.setWidth("250px"); select.setNullSelectionAllowed(false); select.setMultiSelect(false); select.setNewItemsAllowed(false); select.setImmediate(true); return select; } private NativeSelect buildRoleNameSelect(final NativeSelect resourceTypeSelect, final NativeSelect resourceSelect) { NativeSelect roleNameSelect = new NativeSelect(); roleNameSelect.setMultiSelect(false); roleNameSelect.setNewItemsAllowed(false); roleNameSelect.setNullSelectionAllowed(false); roleNameSelect.setImmediate(true); roleNameSelect.setRequired(true); roleNameSelect.setRequiredError("Role can not be empty."); roleNameSelect.addListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { if (event.getProperty().getValue() instanceof RoleModel) { final List<ResourceType> resourceTypeList = new ArrayList<ResourceType>(); for (final ResourceType resourceType : buildScopeDefinitions( (RoleModel) event.getProperty().getValue())) { if (resourceType != null && !resourceType.equals(ResourceType.COMPONENT)) { resourceTypeList.add(resourceType); } } resourceTypeSelect.removeAllItems(); bind(resourceTypeSelect, resourceTypeList); } } private void bind(NativeSelect resourceTypeSelect, List<ResourceType> resourceTypeList) { enableScoping(resourceTypeSelect, resourceTypeList.size() > 0); final BeanItemContainer<ResourceType> dataSource = new BeanItemContainer<ResourceType>( ResourceType.class, resourceTypeList); resourceTypeSelect.setContainerDataSource(dataSource); resourceTypeSelect.setItemCaptionPropertyId(PropertyId.NAME); if (dataSource.size() > 0) { resourceTypeSelect.setValue(dataSource.getIdByIndex(0)); } } private void enableScoping(NativeSelect resourceTypeSelect, boolean isEnabled) { resourceTypeSelect.setVisible(isEnabled); resourceSelect.setVisible(isEnabled); } }); return roleNameSelect; } private void bind(HorizontalLayout grantRow, Grant grant) throws EscidocClientException { NativeSelect roleNameSelect = (NativeSelect) grantRow.getComponent(0); roleNameSelect.setContainerDataSource(buildRoleNameDataSource()); roleNameSelect.setItemCaptionPropertyId(PropertyId.NAME); Collection<?> collection = roleNameSelect.getContainerDataSource().getItemIds(); for (Object object : collection) { ResourceModel rm = (ResourceModel) object; if (grant.getProperties() == null || grant.getProperties().getRole() == null || grant.getProperties().getRole().getXLinkTitle() == null) { return; } // LOG.debug(" Inside " + rm.getName()); if (rm.getName().equalsIgnoreCase(grant.getProperties().getRole().getXLinkTitle())) { // THIS ONE TAKES TOO LONG FOR SOME REASON roleNameSelect.setValue(rm); } } bindResourceType(grantRow, (RoleModel) roleNameSelect.getValue(), grant); } private void bindResourceType(HorizontalLayout grantRow, RoleModel value, Grant grant) throws EscidocClientException { if (value == null) { router.getMainWindow().showNotification("Inconsistency Detected", "There was a grant which does no longer exist as a role: " + grant.getXLinkTitle()); } else { final List<ResourceType> resourceTypeList = buildScopeDefinitions(value); NativeSelect resourceTypeSelect = (NativeSelect) grantRow.getComponent(1); final BeanItemContainer<ResourceType> dataSource = new BeanItemContainer<ResourceType>( ResourceType.class, resourceTypeList); resourceTypeSelect.setContainerDataSource(dataSource); resourceTypeSelect.setItemCaptionPropertyId(PropertyId.NAME); // TODO refactor this if (dataSource.size() > 0 && (NativeSelect) grantRow.getComponent(2) != null) { resourceTypeSelect.setValue(dataSource.getIdByIndex(0)); loadData((NativeSelect) grantRow.getComponent(2), dataSource.getIdByIndex(0)); for (Object object : ((NativeSelect) grantRow.getComponent(2)).getContainerDataSource() .getItemIds()) { Reference assignedOn = grant.getProperties().getAssignedOn(); if (assignedOn == null) { LOG.debug("no resource: " + assignedOn); } else if (assignedOn != null && getRoleName(object).equalsIgnoreCase(assignedOn.getXLinkTitle())) { ((NativeSelect) grantRow.getComponent(2)).select(object); } } } } } private static String getRoleName(Object object) { return ((ResourceModel) object).getName(); } private static List<ResourceType> buildScopeDefinitions(RoleModel value) { final List<ResourceType> resourceTypeList = new ArrayList<ResourceType>(); for (ScopeDef scopeDef : OnRoleSelect.getScopeDefinitions(value)) { final ResourceType resourceType = ResourceType.convert(scopeDef.getRelationAttributeObjectType()); if (resourceType != null && !resourceType.equals(ResourceType.COMPONENT)) { resourceTypeList.add(resourceType); } } return resourceTypeList; } private void loadData(NativeSelect assignedOn, ResourceType type) throws UnsupportedOperationException, EscidocClientException { final BeanItemContainer<ResourceModel> dataSource = newContainer(); for (final ResourceModel rm : findAll(type)) { dataSource.addItem(rm); } configureList(assignedOn, dataSource); } private static void configureList(NativeSelect assignedOn, final BeanItemContainer<ResourceModel> container) { assignedOn.setContainerDataSource(container); assignedOn.setItemCaptionPropertyId(PropertyId.NAME); } private static BeanItemContainer<ResourceModel> newContainer() { return new BeanItemContainer<ResourceModel>(ResourceModel.class); } private List<ResourceModel> findAll(ResourceType type) throws EscidocClientException { List<ResourceModel> list = repositories.findByType(type).findAll(); Collections.sort(list, new Comparator<ResourceModel>() { @Override public int compare(ResourceModel o1, ResourceModel o2) { ResourceModel p1 = o1; ResourceModel p2 = o2; return p1.getName().compareToIgnoreCase(p2.getName()); } }); return list; } private BeanItemContainer<ResourceModel> roleNameDataSource; private BeanItemContainer<ResourceModel> buildRoleNameDataSource() throws EscidocClientException { if (roleNameDataSource == null) { roleNameDataSource = new BeanItemContainer<ResourceModel>(ResourceModel.class); for (ResourceModel resourceModel : repositories.role().findAll()) { if (RoleModel.isValid(resourceModel)) { BeanItem<ResourceModel> item = roleNameDataSource.addItem(resourceModel); Preconditions.checkNotNull(item, "item is null: %s", item); } roleNameDataSource.addItem(resourceModel.getName()); } } return roleNameDataSource; } private Button buildRemoveButton(int rowNumber, Grant grant) { Button removeButton = new Button(); removeButton.setIcon(new ThemeResource("images/assets/minus.png")); removeButton.setData(Integer.valueOf(rowNumber)); removeButton.addListener(new OnRemoveGrant(grant, groupId, repositories, router.getMainWindow())); return removeButton; } private final class OnRemoveGrant implements Button.ClickListener { private Grant grant; private Repositories repos; private Window mainWindow; private String groupId; public OnRemoveGrant(Grant grant, String groupId, Repositories repos, Window mainWindow) { Preconditions.checkNotNull(grant, "grant is null: %s", grant); Preconditions.checkNotNull(groupId, "groupId is null: %s", groupId); Preconditions.checkNotNull(repos, "repo is null: %s", repos); Preconditions.checkNotNull(mainWindow, "mainWindow is null: %s", mainWindow); this.grant = grant; this.repos = repos; this.groupId = groupId; this.mainWindow = mainWindow; } @Override public void buttonClick(final ClickEvent event) { try { revokeGrantInServer(); updateView(event); showSuccessMessage(); } catch (EscidocClientException e) { showErrorMessage(e); } } private void showErrorMessage(EscidocClientException e) { mainWindow.showNotification("Error Message", "Something wrong happens. Cause: " + e.getMessage(), Notification.TYPE_ERROR_MESSAGE); } private void showSuccessMessage() { mainWindow.showNotification("", "Sucessfully revoke " + grant.getXLinkTitle() + " from " + groupId, Notification.TYPE_TRAY_NOTIFICATION); } private void revokeGrantInServer() throws EscidocClientException { repos.group().revokeGrant(groupId, grant); } private void updateView(final ClickEvent event) { VerticalLayout component = (VerticalLayout) event.getButton().getParent().getParent(); component.removeComponent(event.getButton().getParent()); } } }