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.db.CmsUserExportSettings;
031import org.opencms.file.CmsUser;
032import org.opencms.main.CmsException;
033import org.opencms.main.OpenCms;
034import org.opencms.security.I_CmsPrincipal;
035import org.opencms.ui.A_CmsUI;
036import org.opencms.ui.components.CmsBasicDialog;
037import org.opencms.util.CmsStringUtil;
038import org.opencms.util.CmsUUID;
039
040import java.io.ByteArrayInputStream;
041import java.io.InputStream;
042import java.lang.reflect.InvocationTargetException;
043import java.lang.reflect.Method;
044import java.util.ArrayList;
045import java.util.Arrays;
046import java.util.Collections;
047import java.util.Iterator;
048import java.util.List;
049import java.util.Map;
050
051import com.vaadin.server.FileDownloader;
052import com.vaadin.server.Resource;
053import com.vaadin.server.StreamResource;
054import com.vaadin.ui.Button;
055import com.vaadin.ui.Window;
056
057/**
058 * Class to export user.<p>
059 */
060public abstract class A_CmsImportExportUserDialog extends CmsBasicDialog {
061
062    /** The "bom" bytes as String that need to be placed at the very beginning of the produced csv. */
063    private static final String BOM = "\ufeff";
064
065    /**vaadin serial id. */
066    private static final long serialVersionUID = -3990661225158677324L;
067
068    /**Non technical fields to be exported in reduced export. */
069    private static final List<String> NON_TECHNICAL_VALUES = Arrays.asList(
070        "description",
071        "lastname",
072        "firstname",
073        "email",
074        "address",
075        "zipcode",
076        "city",
077        "country");
078
079    /**File downloader. */
080    private FileDownloader m_fileDownloader;
081
082    /**Ou name to export from or import to. */
083    protected String m_ou;
084
085    /**Window. */
086    protected Window m_window;
087
088    /**
089     * Init method.<p>
090     *
091     * @param ou OU
092     * @param window window
093     */
094    protected void init(String ou, Window window) {
095
096        try {
097            displayResourceInfoDirectly(
098                Collections.singletonList(
099                    CmsAccountsApp.getOUInfo(
100                        OpenCms.getOrgUnitManager().readOrganizationalUnit(A_CmsUI.getCmsObject(), ou))));
101        } catch (CmsException e) {
102            //
103        }
104
105        m_ou = ou;
106        m_window = window;
107        getDownloadButton().setEnabled(true);
108        initDownloadButton();
109
110        getCloseButton().addClickListener(event -> window.close());
111    }
112
113    /**
114     * Initializes the download button.<p>
115     */
116    protected void initDownloadButton() {
117
118        if (m_fileDownloader != null) {
119            m_fileDownloader.remove();
120        }
121        m_fileDownloader = new FileDownloader(getDownloadResource());
122        m_fileDownloader.extend(getDownloadButton());
123    }
124
125    /**
126     * Checks if the user can be exported.<p>
127     *
128     * @param exportUser the suer to check
129     *
130     * @return <code>true</code> if the user can be exported
131     */
132    protected boolean isExportable(CmsUser exportUser) {
133
134        return exportUser.getFlags() < I_CmsPrincipal.FLAG_CORE_LIMIT;
135    }
136
137    /**
138     * Gets the close button from layout.
139     * @return Button
140     *  */
141    abstract Button getCloseButton();
142
143    /**
144     * Gets the download button from layout.
145     * @return Button
146     *  */
147    abstract Button getDownloadButton();
148
149    /**
150     * Save export file.<p>
151     * @return InputStream
152     */
153    ByteArrayInputStream getExportStream() {
154
155        //TODO use same CSV Writer like currently used in Apollo
156
157        Map<CmsUUID, CmsUser> exportUsers = getUserToExport();
158
159        CmsCsvWriter csvWriter = new CmsCsvWriter();
160
161        StringBuffer buffer = new StringBuffer(BOM);
162
163        CmsUserExportSettings settings = OpenCms.getImportExportManager().getUserExportSettings();
164
165        List<String> values = settings.getColumns();
166
167        buffer.append("name");
168        Iterator<String> itValues = values.iterator();
169        List<String> columns = new ArrayList<String>();
170        columns.add("name");
171        while (itValues.hasNext()) {
172            String colName = itValues.next();
173            if (isColumnExportable(colName)) {
174                columns.add(colName);
175            }
176        }
177        String[] cols = new String[columns.size()];
178        csvWriter.addLine(columns.toArray(cols));
179
180        Object[] users = exportUsers.values().toArray();
181
182        for (int i = 0; i < users.length; i++) {
183            CmsUser exportUser = (CmsUser)users[i];
184            String[] colValues = new String[columns.size()];
185            if (!isExportable(exportUser)) {
186                continue;
187            }
188            colValues[0] = exportUser.getSimpleName();
189            int colNumber = 1;
190            itValues = values.iterator();
191            while (itValues.hasNext()) {
192
193                String curValue = itValues.next();
194                if (isColumnExportable(curValue)) {
195                    try {
196                        Method method = CmsUser.class.getMethod(
197                            "get" + curValue.substring(0, 1).toUpperCase() + curValue.substring(1));
198                        String curOutput = (String)method.invoke(exportUser);
199                        if (CmsStringUtil.isEmptyOrWhitespaceOnly(curOutput) || curOutput.equals("null")) {
200                            curOutput = (String)exportUser.getAdditionalInfo(curValue);
201                        }
202
203                        if (curValue.equals("password")) {
204                            curOutput = OpenCms.getPasswordHandler().getDigestType() + "_" + curOutput;
205                        }
206
207                        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(curOutput) && !curOutput.equals("null")) {
208                            colValues[colNumber] = curOutput;
209                        }
210                    } catch (NoSuchMethodException e) {
211                        Object obj = exportUser.getAdditionalInfo(curValue);
212                        if (obj != null) {
213                            String curOutput = String.valueOf(obj);
214                            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(curOutput)) {
215                                colValues[colNumber] = curOutput;
216                            }
217                        } else {
218                            colValues[colNumber] = "";
219                        }
220                    } catch (IllegalAccessException e) {
221                        colValues[colNumber] = "";
222                    } catch (InvocationTargetException e) {
223                        colValues[colNumber] = "";
224                    }
225                    if (colValues[colNumber] == null) {
226                        colValues[colNumber] = "";
227                    }
228                    colNumber++;
229                }
230            }
231            csvWriter.addLine(colValues);
232
233        }
234        return new ByteArrayInputStream(csvWriter.toString().getBytes());
235    }
236
237    /**
238     * Gets the user to be exported.<p>
239     *
240     * @return Map of user
241     */
242    abstract Map<CmsUUID, CmsUser> getUserToExport();
243
244    /**
245     * Export including technical fields.<p>
246     *
247     * @return boolean
248     */
249    abstract boolean isExportWithTechnicalFields();
250
251    /**
252     * Get download resource for export.<p>
253     *
254     * @return Resource
255     */
256    private Resource getDownloadResource() {
257
258        return new StreamResource(new StreamResource.StreamSource() {
259
260            private static final long serialVersionUID = -8868657402793427460L;
261
262            public InputStream getStream() {
263
264                return getExportStream();
265            }
266        }, "User_Export.csv");
267    }
268
269    /**
270     * Checks if given column is to be exported.<p>
271     *
272     * @param colName to be checked
273     * @return boolean
274     */
275    private boolean isColumnExportable(String colName) {
276
277        if (isExportWithTechnicalFields()) {
278            return true;
279        }
280        return NON_TECHNICAL_VALUES.contains(colName.toLowerCase());
281    }
282}