001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.upgrade.v6_2_0;
016    
017    import com.liferay.document.library.kernel.model.DLFolderConstants;
018    import com.liferay.document.library.kernel.store.DLStoreUtil;
019    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.model.CompanyConstants;
023    import com.liferay.portal.kernel.model.ResourceConstants;
024    import com.liferay.portal.kernel.model.ResourcePermission;
025    import com.liferay.portal.kernel.model.RoleConstants;
026    import com.liferay.portal.kernel.security.permission.ActionKeys;
027    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.FileUtil;
030    import com.liferay.portal.kernel.util.MimeTypesUtil;
031    import com.liferay.portal.kernel.util.PortalUtil;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
035    
036    import java.sql.PreparedStatement;
037    import java.sql.ResultSet;
038    import java.sql.Timestamp;
039    
040    import java.util.ArrayList;
041    import java.util.HashMap;
042    import java.util.List;
043    import java.util.Map;
044    
045    /**
046     * @author Eudaldo Alonso
047     */
048    public abstract class BaseUpgradeAttachments extends UpgradeProcess {
049    
050            protected long addDLFileEntry(
051                            long groupId, long companyId, long userId, String className,
052                            long classPK, String userName, Timestamp createDate,
053                            long repositoryId, long folderId, String name, String extension,
054                            String mimeType, String title, long size)
055                    throws Exception {
056    
057                    PreparedStatement ps = null;
058    
059                    try {
060                            long fileEntryId = increment();
061    
062                            StringBundler sb = new StringBundler(9);
063    
064                            sb.append("insert into DLFileEntry (uuid_, fileEntryId, groupId, ");
065                            sb.append("companyId, userId, userName, createDate, ");
066                            sb.append("modifiedDate, classNameId, classPK, repositoryId, ");
067                            sb.append("folderId, name, extension, mimeType, title, ");
068                            sb.append("description, extraSettings, fileEntryTypeId, version, ");
069                            sb.append("size_, readCount, smallImageId, largeImageId, ");
070                            sb.append("custom1ImageId, custom2ImageId) values (?, ?, ?, ?, ");
071                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
072                            sb.append("?, ?, ?, ?)");
073    
074                            String sql = sb.toString();
075    
076                            ps = connection.prepareStatement(sql);
077    
078                            ps.setString(1, PortalUUIDUtil.generate());
079                            ps.setLong(2, fileEntryId);
080                            ps.setLong(3, groupId);
081                            ps.setLong(4, companyId);
082                            ps.setLong(5, userId);
083                            ps.setString(6, userName);
084                            ps.setTimestamp(7, createDate);
085                            ps.setTimestamp(8, createDate);
086                            ps.setLong(9, PortalUtil.getClassNameId(className));
087                            ps.setLong(10, classPK);
088                            ps.setLong(11, repositoryId);
089                            ps.setLong(12, folderId);
090                            ps.setString(13, name);
091                            ps.setString(14, extension);
092                            ps.setString(15, mimeType);
093                            ps.setString(16, title);
094                            ps.setString(17, StringPool.BLANK);
095                            ps.setString(18, StringPool.BLANK);
096                            ps.setLong(19, 0);
097                            ps.setString(20, "1.0");
098                            ps.setLong(21, size);
099                            ps.setInt(22, 0);
100                            ps.setLong(23, 0);
101                            ps.setLong(24, 0);
102                            ps.setLong(25, 0);
103                            ps.setLong(26, 0);
104    
105                            ps.executeUpdate();
106    
107                            Map<String, Long> bitwiseValues = getBitwiseValues(
108                                    "com.liferay.portlet.documentlibrary.model.DLFileEntry");
109    
110                            List<String> actionIds = new ArrayList<>();
111    
112                            actionIds.add(ActionKeys.VIEW);
113    
114                            long bitwiseValue = getBitwiseValue(bitwiseValues, actionIds);
115    
116                            addResourcePermission(
117                                    companyId,
118                                    "com.liferay.portlet.documentlibrary.model.DLFileEntry",
119                                    fileEntryId, getRoleId(companyId, RoleConstants.GUEST),
120                                    bitwiseValue);
121                            addResourcePermission(
122                                    companyId,
123                                    "com.liferay.portlet.documentlibrary.model.DLFileEntry",
124                                    fileEntryId, getRoleId(companyId, RoleConstants.SITE_MEMBER),
125                                    bitwiseValue);
126    
127                            return fileEntryId;
128                    }
129                    catch (Exception e) {
130                            if (_log.isWarnEnabled()) {
131                                    _log.warn("Unable to add file entry " + name, e);
132                            }
133    
134                            return -1;
135                    }
136                    finally {
137                            DataAccess.cleanUp(ps);
138                    }
139            }
140    
141            protected void addDLFileVersion(
142                            long fileVersionId, long groupId, long companyId, long userId,
143                            String userName, Timestamp createDate, long repositoryId,
144                            long folderId, long fileEntryId, String extension, String mimeType,
145                            String title, long size)
146                    throws Exception {
147    
148                    PreparedStatement ps = null;
149    
150                    try {
151                            StringBundler sb = new StringBundler(8);
152    
153                            sb.append("insert into DLFileVersion (uuid_, fileVersionId, ");
154                            sb.append("groupId, companyId, userId, userName, createDate, ");
155                            sb.append("modifiedDate, repositoryId, folderId, fileEntryId, ");
156                            sb.append("extension, mimeType, title, description, changeLog, ");
157                            sb.append("extraSettings, fileEntryTypeId, version, size_, ");
158                            sb.append("status, statusByUserId, statusByUserName, statusDate) ");
159                            sb.append("values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
160                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?)");
161    
162                            String sql = sb.toString();
163    
164                            ps = connection.prepareStatement(sql);
165    
166                            ps.setString(1, PortalUUIDUtil.generate());
167                            ps.setLong(2, fileVersionId);
168                            ps.setLong(3, groupId);
169                            ps.setLong(4, companyId);
170                            ps.setLong(5, userId);
171                            ps.setString(6, userName);
172                            ps.setTimestamp(7, createDate);
173                            ps.setTimestamp(8, createDate);
174                            ps.setLong(9, repositoryId);
175                            ps.setLong(10, folderId);
176                            ps.setLong(11, fileEntryId);
177                            ps.setString(12, extension);
178                            ps.setString(13, mimeType);
179                            ps.setString(14, title);
180                            ps.setString(15, StringPool.BLANK);
181                            ps.setString(16, StringPool.BLANK);
182                            ps.setString(17, StringPool.BLANK);
183                            ps.setLong(18, 0);
184                            ps.setString(19, "1.0");
185                            ps.setLong(20, size);
186                            ps.setInt(21, 0);
187                            ps.setLong(22, userId);
188                            ps.setString(23, userName);
189                            ps.setTimestamp(24, createDate);
190    
191                            ps.executeUpdate();
192                    }
193                    catch (Exception e) {
194                            if (_log.isWarnEnabled()) {
195                                    _log.warn(
196                                            "Unable to add file version 1.0 for file entry " + title,
197                                            e);
198                            }
199                    }
200                    finally {
201                            DataAccess.cleanUp(ps);
202                    }
203            }
204    
205            protected long addDLFolder(
206                            long folderId, long groupId, long companyId, long userId,
207                            String userName, Timestamp createDate, long repositoryId,
208                            boolean mountPoint, long parentFolderId, String name,
209                            boolean hidden)
210                    throws Exception {
211    
212                    PreparedStatement ps = null;
213    
214                    try {
215                            StringBundler sb = new StringBundler(8);
216    
217                            sb.append("insert into DLFolder (uuid_, folderId, groupId, ");
218                            sb.append("companyId, userId, userName, createDate, ");
219                            sb.append("modifiedDate, repositoryId, mountPoint, ");
220                            sb.append("parentFolderId, name, description, lastPostDate, ");
221                            sb.append("defaultFileEntryTypeId, hidden_, ");
222                            sb.append("overrideFileEntryTypes, status, statusByUserId, ");
223                            sb.append("statusByUserName, statusDate) values (?, ?, ?, ?, ?, ");
224                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
225    
226                            String sql = sb.toString();
227    
228                            ps = connection.prepareStatement(sql);
229    
230                            ps.setString(1, PortalUUIDUtil.generate());
231                            ps.setLong(2, folderId);
232                            ps.setLong(3, groupId);
233                            ps.setLong(4, companyId);
234                            ps.setLong(5, userId);
235                            ps.setString(6, userName);
236                            ps.setTimestamp(7, createDate);
237                            ps.setTimestamp(8, createDate);
238                            ps.setLong(9, repositoryId);
239                            ps.setBoolean(10, mountPoint);
240                            ps.setLong(11, parentFolderId);
241                            ps.setString(12, name);
242                            ps.setString(13, StringPool.BLANK);
243                            ps.setTimestamp(14, createDate);
244                            ps.setLong(15, 0);
245                            ps.setBoolean(16, hidden);
246                            ps.setBoolean(17, false);
247                            ps.setLong(18, 0);
248                            ps.setLong(19, userId);
249                            ps.setString(20, userName);
250                            ps.setTimestamp(21, createDate);
251    
252                            ps.executeUpdate();
253    
254                            Map<String, Long> bitwiseValues = getBitwiseValues(
255                                    "com.liferay.portlet.documentlibrary.model.DLFolder");
256    
257                            List<String> guestActionIds = new ArrayList<>();
258    
259                            guestActionIds.add(ActionKeys.VIEW);
260    
261                            long guestBitwiseValue = getBitwiseValue(
262                                    bitwiseValues, guestActionIds);
263    
264                            addResourcePermission(
265                                    companyId, "com.liferay.portlet.documentlibrary.model.DLFolder",
266                                    folderId, getRoleId(companyId, RoleConstants.GUEST),
267                                    guestBitwiseValue);
268    
269                            List<String> siteMemberActionIds = new ArrayList<>();
270    
271                            siteMemberActionIds.add(ActionKeys.ADD_DOCUMENT);
272                            siteMemberActionIds.add(ActionKeys.ADD_SUBFOLDER);
273                            siteMemberActionIds.add(ActionKeys.VIEW);
274    
275                            long siteMemberBitwiseValue = getBitwiseValue(
276                                    bitwiseValues, siteMemberActionIds);
277    
278                            addResourcePermission(
279                                    companyId, "com.liferay.portlet.documentlibrary.model.DLFolder",
280                                    folderId, getRoleId(companyId, RoleConstants.SITE_MEMBER),
281                                    siteMemberBitwiseValue);
282    
283                            return folderId;
284                    }
285                    catch (Exception e) {
286                            if (_log.isWarnEnabled()) {
287                                    _log.warn("Unable to add folder " + name, e);
288                            }
289    
290                            return -1;
291                    }
292                    finally {
293                            DataAccess.cleanUp(ps);
294                    }
295            }
296    
297            protected long addRepository(
298                            long groupId, long companyId, long userId, String userName,
299                            Timestamp createDate, long classNameId, String portletId)
300                    throws Exception {
301    
302                    long repositoryId = increment();
303    
304                    long folderId = addDLFolder(
305                            increment(), groupId, companyId, userId, userName, createDate,
306                            repositoryId, true, DLFolderConstants.DEFAULT_PARENT_FOLDER_ID,
307                            portletId, true);
308    
309                    if (folderId < 0) {
310                            return -1;
311                    }
312    
313                    PreparedStatement ps = null;
314    
315                    try {
316                            StringBundler sb = new StringBundler(5);
317    
318                            sb.append("insert into Repository (uuid_, repositoryId, groupId, ");
319                            sb.append("companyId, userId, userName, createDate, ");
320                            sb.append("modifiedDate, classNameId, name, description, ");
321                            sb.append("portletId, typeSettings, dlFolderId) values (?, ?, ?, ");
322                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
323    
324                            ps = connection.prepareStatement(sb.toString());
325    
326                            ps.setString(1, PortalUUIDUtil.generate());
327                            ps.setLong(2, repositoryId);
328                            ps.setLong(3, groupId);
329                            ps.setLong(4, companyId);
330                            ps.setLong(5, userId);
331                            ps.setString(6, userName);
332                            ps.setTimestamp(7, createDate);
333                            ps.setTimestamp(8, createDate);
334                            ps.setLong(9, classNameId);
335                            ps.setString(10, portletId);
336                            ps.setString(11, StringPool.BLANK);
337                            ps.setString(12, portletId);
338                            ps.setString(13, StringPool.BLANK);
339                            ps.setLong(14, folderId);
340    
341                            ps.executeUpdate();
342    
343                            return repositoryId;
344                    }
345                    catch (Exception e) {
346                            if (_log.isWarnEnabled()) {
347                                    _log.warn(
348                                            "Unable to add repository for portlet " + portletId, e);
349                            }
350    
351                            return -1;
352                    }
353                    finally {
354                            DataAccess.cleanUp(ps);
355                    }
356            }
357    
358            protected void addResourcePermission(
359                            long companyId, String className, long primKey, long roleId,
360                            long actionIds)
361                    throws Exception {
362    
363                    PreparedStatement ps = null;
364    
365                    try {
366                            long resourcePermissionId = increment(
367                                    ResourcePermission.class.getName());
368    
369                            StringBundler sb = new StringBundler(3);
370    
371                            sb.append("insert into ResourcePermission (resourcePermissionId, ");
372                            sb.append("companyId, name, scope, primKey, roleId, ownerId, ");
373                            sb.append("actionIds) values (?, ?, ?, ?, ?, ?, ?, ?)");
374    
375                            String sql = sb.toString();
376    
377                            ps = connection.prepareStatement(sql);
378    
379                            ps.setLong(1, resourcePermissionId);
380                            ps.setLong(2, companyId);
381                            ps.setString(3, className);
382                            ps.setInt(4, ResourceConstants.SCOPE_INDIVIDUAL);
383                            ps.setLong(5, primKey);
384                            ps.setLong(6, roleId);
385                            ps.setLong(7, 0);
386                            ps.setLong(8, actionIds);
387    
388                            ps.executeUpdate();
389                    }
390                    catch (Exception e) {
391                            if (_log.isWarnEnabled()) {
392                                    _log.warn("Unable to add resource permission " + className, e);
393                            }
394                    }
395                    finally {
396                            DataAccess.cleanUp(ps);
397                    }
398            }
399    
400            @Override
401            protected void doUpgrade() throws Exception {
402                    updateAttachments();
403            }
404    
405            protected String[] getAttachments(
406                            long companyId, long containerModelId, long resourcePrimKey)
407                    throws Exception {
408    
409                    String dirName = getDirName(containerModelId, resourcePrimKey);
410    
411                    return DLStoreUtil.getFileNames(
412                            companyId, CompanyConstants.SYSTEM, dirName);
413            }
414    
415            protected long getBitwiseValue(
416                    Map<String, Long> bitwiseValues, List<String> actionIds) {
417    
418                    long bitwiseValue = 0;
419    
420                    for (String actionId : actionIds) {
421                            Long actionIdBitwiseValue = bitwiseValues.get(actionId);
422    
423                            if (actionIdBitwiseValue == null) {
424                                    continue;
425                            }
426    
427                            bitwiseValue |= actionIdBitwiseValue;
428                    }
429    
430                    return bitwiseValue;
431            }
432    
433            protected Map<String, Long> getBitwiseValues(String name) throws Exception {
434                    Map<String, Long> bitwiseValues = _bitwiseValues.get(name);
435    
436                    if (bitwiseValues != null) {
437                            return bitwiseValues;
438                    }
439    
440                    PreparedStatement ps = null;
441                    ResultSet rs = null;
442    
443                    try {
444                            ps = connection.prepareStatement(
445                                    "select actionId, bitwiseValue from ResourceAction " +
446                                            "where name = ?");
447    
448                            ps.setString(1, name);
449    
450                            rs = ps.executeQuery();
451    
452                            bitwiseValues = new HashMap<>();
453    
454                            while (rs.next()) {
455                                    String actionId = rs.getString("actionId");
456                                    long bitwiseValue = rs.getLong("bitwiseValue");
457    
458                                    bitwiseValues.put(actionId, bitwiseValue);
459                            }
460    
461                            _bitwiseValues.put(name, bitwiseValues);
462    
463                            return bitwiseValues;
464                    }
465                    finally {
466                            DataAccess.cleanUp(ps, rs);
467                    }
468            }
469    
470            protected abstract String getClassName();
471    
472            protected long getClassNameId() {
473                    return PortalUtil.getClassNameId(getClassName());
474            }
475    
476            protected long getContainerModelFolderId(
477                            long groupId, long companyId, long resourcePrimKey,
478                            long containerModelId, long userId, String userName,
479                            Timestamp createDate)
480                    throws Exception {
481    
482                    return DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
483            }
484    
485            protected abstract String getDirName(
486                    long containerModelId, long resourcePrimKey);
487    
488            protected long getFolderId(
489                            long groupId, long companyId, long userId, String userName,
490                            Timestamp createDate, long repositoryId, long parentFolderId,
491                            String name, boolean hidden)
492                    throws Exception {
493    
494                    if ((repositoryId < 0) || (parentFolderId < 0)) {
495                            return -1;
496                    }
497    
498                    PreparedStatement ps = null;
499                    ResultSet rs = null;
500    
501                    try {
502                            ps = connection.prepareStatement(
503                                    "select folderId from DLFolder where repositoryId = ? and " +
504                                            "parentFolderId = ? and name = ?");
505    
506                            ps.setLong(1, repositoryId);
507                            ps.setLong(2, parentFolderId);
508                            ps.setString(3, name);
509    
510                            rs = ps.executeQuery();
511    
512                            while (rs.next()) {
513                                    long folderId = rs.getLong(1);
514    
515                                    return folderId;
516                            }
517                    }
518                    finally {
519                            DataAccess.cleanUp(ps);
520                    }
521    
522                    return addDLFolder(
523                            increment(), groupId, companyId, userId, userName, createDate,
524                            repositoryId, false, parentFolderId, name, hidden);
525            }
526    
527            protected abstract String getPortletId();
528    
529            protected long getRepositoryId(
530                            long groupId, long companyId, long userId, String userName,
531                            Timestamp createDate, long classNameId, String portletId)
532                    throws Exception {
533    
534                    PreparedStatement ps = null;
535                    ResultSet rs = null;
536    
537                    try {
538                            ps = connection.prepareStatement(
539                                    "select repositoryId from Repository where groupId = ? and " +
540                                            "name = ? and portletId = ?");
541    
542                            ps.setLong(1, groupId);
543                            ps.setString(2, portletId);
544                            ps.setString(3, portletId);
545    
546                            rs = ps.executeQuery();
547    
548                            while (rs.next()) {
549                                    long repositoryId = rs.getLong(1);
550    
551                                    return repositoryId;
552                            }
553                    }
554                    finally {
555                            DataAccess.cleanUp(ps);
556                    }
557    
558                    return addRepository(
559                            groupId, companyId, userId, userName, createDate, classNameId,
560                            portletId);
561            }
562    
563            protected long getRoleId(long companyId, String name) throws Exception {
564                    String roleIdsKey = companyId + StringPool.POUND + name;
565    
566                    Long roleId = _roleIds.get(roleIdsKey);
567    
568                    if (roleId != null) {
569                            return roleId;
570                    }
571    
572                    PreparedStatement ps = null;
573                    ResultSet rs = null;
574    
575                    try {
576                            ps = connection.prepareStatement(
577                                    "select roleId from Role_ where companyId = ? and name = ?");
578    
579                            ps.setLong(1, companyId);
580                            ps.setString(2, name);
581    
582                            rs = ps.executeQuery();
583    
584                            if (rs.next()) {
585                                    roleId = rs.getLong("roleId");
586                            }
587    
588                            _roleIds.put(roleIdsKey, roleId);
589    
590                            return roleId;
591                    }
592                    finally {
593                            DataAccess.cleanUp(ps, rs);
594                    }
595            }
596    
597            protected abstract void updateAttachments() throws Exception;
598    
599            protected void updateEntryAttachments(
600                            long companyId, long groupId, long resourcePrimKey,
601                            long containerModelId, long userId, String userName)
602                    throws Exception {
603    
604                    String[] attachments = getAttachments(
605                            companyId, containerModelId, resourcePrimKey);
606    
607                    if (ArrayUtil.isEmpty(attachments)) {
608                            return;
609                    }
610    
611                    Timestamp createDate = new Timestamp(System.currentTimeMillis());
612    
613                    long repositoryId = getRepositoryId(
614                            groupId, companyId, userId, userName, createDate,
615                            PortalUtil.getClassNameId(_LIFERAY_REPOSITORY_CLASS_NAME),
616                            getPortletId());
617    
618                    if (repositoryId < 0) {
619                            return;
620                    }
621    
622                    long containerModelFolderId = getContainerModelFolderId(
623                            groupId, companyId, resourcePrimKey, containerModelId, userId,
624                            userName, createDate);
625    
626                    if (containerModelFolderId < 0) {
627                            return;
628                    }
629    
630                    for (String attachment : attachments) {
631                            String name = String.valueOf(
632                                    increment(
633                                            "com.liferay.portlet.documentlibrary.model.DLFileEntry"));
634    
635                            String title = FileUtil.getShortFileName(attachment);
636    
637                            String extension = FileUtil.getExtension(title);
638    
639                            String mimeType = MimeTypesUtil.getExtensionContentType(extension);
640    
641                            try {
642                                    long size = DLStoreUtil.getFileSize(
643                                            companyId, CompanyConstants.SYSTEM, attachment);
644    
645                                    long fileEntryId = addDLFileEntry(
646                                            groupId, companyId, userId, getClassName(), resourcePrimKey,
647                                            userName, createDate, repositoryId, containerModelFolderId,
648                                            name, extension, mimeType, title, size);
649    
650                                    if (fileEntryId < 0) {
651                                            continue;
652                                    }
653    
654                                    addDLFileVersion(
655                                            increment(), groupId, companyId, userId, userName,
656                                            createDate, repositoryId, containerModelFolderId,
657                                            fileEntryId, extension, mimeType, title, size);
658    
659                                    byte[] bytes = DLStoreUtil.getFileAsBytes(
660                                            companyId, CompanyConstants.SYSTEM, attachment);
661    
662                                    DLStoreUtil.addFile(
663                                            companyId, containerModelFolderId, name, false, bytes);
664                            }
665                            catch (Exception e) {
666                                    if (_log.isWarnEnabled()) {
667                                            _log.warn("Unable to add attachment " + attachment, e);
668                                    }
669                            }
670    
671                            try {
672                                    DLStoreUtil.deleteFile(
673                                            companyId, CompanyConstants.SYSTEM, attachment);
674                            }
675                            catch (Exception e) {
676                                    if (_log.isWarnEnabled()) {
677                                            _log.warn("Unable to delete attachment " + attachment, e);
678                                    }
679                            }
680                    }
681            }
682    
683            private static final String _LIFERAY_REPOSITORY_CLASS_NAME =
684                    "com.liferay.portal.repository.liferayrepository.LiferayRepository";
685    
686            private static final Log _log = LogFactoryUtil.getLog(
687                    BaseUpgradeAttachments.class);
688    
689            private final Map<String, Map<String, Long>> _bitwiseValues =
690                    new HashMap<>();
691            private final Map<String, Long> _roleIds = new HashMap<>();
692    
693    }