001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Martin Pernollet 018 */ 019 020package org.nuxeo.ecm.platform.groups.audit.service.acl; 021 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.Set; 026 027import org.apache.poi.ss.usermodel.Cell; 028import org.apache.poi.ss.usermodel.CellStyle; 029import org.nuxeo.ecm.platform.groups.audit.service.acl.ReportLayoutSettings.SpanMode; 030import org.nuxeo.ecm.platform.groups.audit.service.acl.excel.ByteColor; 031import org.nuxeo.ecm.platform.groups.audit.service.acl.excel.ExcelBuilder; 032import org.nuxeo.ecm.platform.groups.audit.service.acl.filter.IContentFilter; 033 034import com.google.common.collect.Multimap; 035 036/** 037 * An excel layout builder that uses one group of columns per user, using one column for each right type (read, write, 038 * etc). 039 * 040 * @author Martin Pernollet <mpernollet@nuxeo.com> 041 */ 042public class AclExcelLayoutBuilderMultiColumn extends AclExcelLayoutBuilder { 043 protected static int USERS_ROW = 0; 044 045 protected static int PERMISSIONS_ROW = 1; 046 047 public static ReportLayoutSettings defaultLayout() { 048 ReportLayoutSettings layout = new ReportLayoutSettings(); 049 layout.userHeaderHeight = -1; 050 layout.userHeaderRotation = 0; 051 layout.aclHeaderHeight = -1;// fit vertically full ACL name 1800; 052 layout.aclHeaderRotation = 0; 053 054 layout.fileTreeColumnWidth = 2.5; // in number of char 055 layout.aclColumnWidth = 2.5; 056 layout.defaultRowHeight = 100; 057 layout.splitPaneX = 500; 058 layout.splitPaneY = 1500; 059 layout.freezePaneRowSplit = 2; 060 layout.treeLineCursorRowStart = 2; 061 062 layout.aclHeaderCommentColSpan = 10; 063 layout.aclHeaderCommentRowSpan = 2; 064 layout.aclHeaderFontSize = 6; // in font unit 065 066 layout.spanMode = SpanMode.COLUMN_OVERFLOW_ON_NEXT_SHEETS; 067 068 layout.zoomRatioDenominator = 2; 069 layout.zoomRatioNumerator = 1; 070 071 layout.logoImageFile = "src/main/resources/file-delete.png"; 072 073 return layout; 074 } 075 076 /* Prebuilt styles */ 077 078 protected CellStyle acceptStyle; 079 080 protected CellStyle acceptStyleLeft; 081 082 protected CellStyle acceptStyleRight; 083 084 protected CellStyle denyStyle; 085 086 protected CellStyle denyStyleLeft; 087 088 protected CellStyle denyStyleRight; 089 090 protected CellStyle emptyStyle; 091 092 protected CellStyle emptyStyleLeft; 093 094 protected CellStyle emptyStyleRight; 095 096 protected int logoPictureId = -1; 097 098 public AclExcelLayoutBuilderMultiColumn() { 099 super(defaultLayout()); 100 } 101 102 public AclExcelLayoutBuilderMultiColumn(IContentFilter filter) { 103 this(defaultLayout(), filter); 104 } 105 106 public AclExcelLayoutBuilderMultiColumn(ReportLayoutSettings layout, IContentFilter filter) { 107 super(layout, filter); 108 } 109 110 @Override 111 protected void renderInit() { 112 super.renderInit(); 113 acceptStyle = excel.newColoredCellStyle(ByteColor.GREEN); 114 115 acceptStyleLeft = excel.newColoredCellStyle(ByteColor.GREEN); 116 acceptStyleLeft.setBorderLeft(CellStyle.BORDER_THIN); 117 acceptStyleLeft.setLeftBorderColor(excel.getColor(ByteColor.BLACK).getIndex()); 118 119 acceptStyleRight = excel.newColoredCellStyle(ByteColor.GREEN); 120 acceptStyleRight.setBorderRight(CellStyle.BORDER_THIN); 121 acceptStyleRight.setRightBorderColor(excel.getColor(ByteColor.BLACK).getIndex()); 122 123 denyStyle = excel.newColoredCellStyle(ByteColor.RED); 124 denyStyle.setFillPattern(CellStyle.THIN_FORWARD_DIAG); // TODO: 125 // generaliser 126 // autres 127 // cellules 128 denyStyle.setFillBackgroundColor(excel.getColor(ByteColor.WHITE).getIndex()); 129 130 denyStyleLeft = excel.newColoredCellStyle(ByteColor.RED); 131 denyStyleLeft.setBorderLeft(CellStyle.BORDER_THIN); 132 denyStyleLeft.setLeftBorderColor(excel.getColor(ByteColor.BLACK).getIndex()); 133 134 denyStyleRight = excel.newColoredCellStyle(ByteColor.RED); 135 denyStyleRight.setBorderRight(CellStyle.BORDER_THIN); 136 denyStyleRight.setRightBorderColor(excel.getColor(ByteColor.BLACK).getIndex()); 137 138 emptyStyle = excel.newColoredCellStyle(ByteColor.WHITE); 139 140 emptyStyleLeft = excel.newColoredCellStyle(ByteColor.WHITE); 141 emptyStyleLeft.setBorderLeft(CellStyle.BORDER_THIN); 142 emptyStyleLeft.setLeftBorderColor(excel.getColor(ByteColor.BLACK).getIndex()); 143 144 emptyStyleRight = excel.newColoredCellStyle(ByteColor.WHITE); 145 emptyStyleRight.setBorderRight(CellStyle.BORDER_THIN); 146 emptyStyleRight.setRightBorderColor(excel.getColor(ByteColor.BLACK).getIndex()); 147 148 if (layoutSettings.logoImageFile != null) 149 try { 150 logoPictureId = excel.loadPicture(layoutSettings.logoImageFile); 151 } catch (IOException e) { 152 log.error(e, e); 153 } 154 } 155 156 /* HEADER RENDERING */ 157 158 /** 159 * Write users and groups on the first row. Memorize the user (or group) column which can later be retrieved with 160 * getColumn(user) 161 */ 162 @Override 163 protected void renderHeader(int tableStartColumn, Set<String> userOrGroups, Set<String> permissions) { 164 renderHeaderPicture(); 165 renderHeaderUsers(tableStartColumn, userOrGroups, permissions); 166 renderHeaderAcl(userOrGroups, permissions); 167 formatHeaderRowHeight(); 168 } 169 170 protected void renderHeaderPicture() { 171 // excel.mergeRange(USERS_ROW, 0, PERMISSIONS_ROW, tableStartColumn-1); 172 excel.setPicture(logoPictureId, 0, 0, false); 173 } 174 175 protected void renderHeaderUsers(int tableStartColumn, Set<String> userOrGroups, Set<String> permissions) { 176 177 int userColumn = tableStartColumn; 178 for (String user : userOrGroups) { 179 // render the user column header 180 excel.setCell(USERS_ROW, userColumn, user, userHeaderStyle); 181 layout.setUserColumn(userColumn, user); 182 183 // merge cells indicating user name 184 final int from = userColumn; 185 final int to = userColumn + permissions.size() - 1; 186 if (from < ExcelBuilder.LAST_COLUMN && to < ExcelBuilder.LAST_COLUMN) 187 excel.mergeRange(USERS_ROW, from, USERS_ROW, to); 188 189 userColumn += permissions.size(); 190 log.debug("user header: " + USERS_ROW + "," + userColumn + " > " + user); 191 } 192 } 193 194 protected void renderHeaderAcl(Set<String> userOrGroups, Set<String> permissions) { 195 for (String user : userOrGroups) { 196 // render ACL column header for this user 197 int userColumn; 198 int aclColumn = 0; 199 int aclHeaderColumn = 0; 200 String aclHeaderText; 201 String aclHeaderShort; 202 203 for (String permission : permissions) { 204 userColumn = layout.getUserColumn(user); 205 aclHeaderColumn = userColumn + aclColumn; 206 aclHeaderText = permission;// formatPermission(permission); 207 aclHeaderShort = formatPermission(permission); 208 209 Cell cell = excel.setCell(PERMISSIONS_ROW, aclHeaderColumn, aclHeaderShort, aclHeaderStyle); 210 excel.setColumnWidth(aclHeaderColumn, (int) (layoutSettings.aclColumnWidth * CELL_WIDTH_UNIT)); 211 212 // add a comment with the acl complete name 213 if ((aclHeaderColumn + layoutSettings.aclHeaderCommentColSpan) < ExcelBuilder.LAST_COLUMN) 214 excel.addComment(cell, aclHeaderText, PERMISSIONS_ROW, aclHeaderColumn, 215 layoutSettings.aclHeaderCommentColSpan, layoutSettings.aclHeaderCommentRowSpan); 216 217 layout.setUserAclColumn(aclHeaderColumn, Pair.of(user, permission)); 218 aclColumn++; 219 220 log.debug("permission header: " + PERMISSIONS_ROW + "," + aclHeaderColumn + " > " 221 + formatPermission(permission)); 222 } 223 } 224 } 225 226 protected void formatHeaderRowHeight() { 227 if (layoutSettings.aclHeaderHeight != -1) 228 excel.setRowHeight(PERMISSIONS_ROW, layoutSettings.aclHeaderHeight); 229 if (layoutSettings.userHeaderHeight != -1) 230 excel.setRowHeight(USERS_ROW, layoutSettings.userHeaderHeight); 231 } 232 233 /* FILE TREE AND MATRIX CONTENT RENDERING */ 234 235 @Override 236 protected void renderAcl(Multimap<String, Pair<String, Boolean>> userAcls) { 237 for (String user : userAcls.keySet()) { 238 List<Pair<String, Boolean>> acls = new ArrayList<Pair<String, Boolean>>(userAcls.get(user)); 239 int last = acls.size() - 1; 240 241 // TODO: IF ACLS not contain an ACL that should be first or last, 242 // thus showing border, post draw white cells 243 244 for (int i = 0; i < acls.size(); i++) { 245 boolean isFirst = false;// (i == 0); 246 boolean isLast = false;// (i == last); 247 248 Pair<String, Boolean> ace = acls.get(i); 249 String permission = ace.a; 250 boolean accept = ace.b; 251 int aclColumn = layout.getUserAclColumn(Pair.of(user, permission)); 252 String aceText = "";// formatAce(ace) 253 254 if (accept) { 255 // draws an accept cell 256 renderAcceptCell(isFirst, isLast, aclColumn, aceText); 257 } else { 258 // draws a deny cell 259 renderDenyCell(isFirst, isLast, aclColumn, aceText); 260 } 261 } 262 // String info = formatAcl(userAcls.get(user)); 263 } 264 } 265 266 /** 267 * Render a cell with a 'deny' color with left, right or no border according to its position. 268 */ 269 protected void renderDenyCell(boolean isFirst, boolean isLast, int aclColumn, String aceText) { 270 if (isFirst) { 271 excel.setCell(treeLineCursor, aclColumn, aceText, denyStyleLeft); 272 } else if (isLast) { 273 excel.setCell(treeLineCursor, aclColumn, aceText, denyStyleRight); 274 } else { 275 excel.setCell(treeLineCursor, aclColumn, aceText, denyStyle); 276 } 277 } 278 279 /** 280 * Render a cell with a 'accept' color with left, right or no border according to its position. 281 */ 282 protected void renderAcceptCell(boolean isFirst, boolean isLast, int aclColumn, String aceText) { 283 if (isFirst) { 284 excel.setCell(treeLineCursor, aclColumn, aceText, acceptStyleLeft); 285 } else if (isLast) { 286 excel.setCell(treeLineCursor, aclColumn, aceText, acceptStyleRight); 287 } else { 288 excel.setCell(treeLineCursor, aclColumn, aceText, acceptStyle); 289 } 290 } 291}