head	1.15;
access;
symbols
	TIGRIS_0_9_2_4:1.10
	TIGRIS_0_9_2_3:1.10
	HELM_PEER_PORT_BRANCH:1.14.0.2
	TURBINE_PEER:1.14
	TIGRIS_0_9_2_1:1.14
	TIGRIS_0_9_2:1.10.0.6
	TIGRIS_0_9_0:1.10.0.4
	TIGRIS_0_8_4:1.10.0.2
	NEWHELM:1.1.1.1
	TIGRIS_NOV_12_2000:1.1.1
	OLDHELM:1.3.0.2
	TIGRIS_NOV_11_2000:1.3;
locks; strict;
comment	@# @;


1.15
date	2001.02.21.03.23.56;	author edk;	state dead;
branches;
next	1.14;

1.14
date	2001.01.26.18.29.00;	author edk;	state Exp;
branches
	1.14.2.1;
next	1.13;

1.13
date	2001.01.26.05.24.05;	author edk;	state dead;
branches;
next	1.12;

1.12
date	2001.01.24.21.41.48;	author leonardr;	state Exp;
branches;
next	1.11;

1.11
date	2001.01.24.20.42.46;	author dlr;	state Exp;
branches;
next	1.10;

1.10
date	2000.12.02.01.45.41;	author leonardr;	state Exp;
branches;
next	1.9;

1.9
date	2000.11.29.19.59.33;	author leonardr;	state Exp;
branches;
next	1.8;

1.8
date	2000.11.20.20.07.32;	author leonardr;	state Exp;
branches;
next	1.7;

1.7
date	2000.11.17.00.29.21;	author leonardr;	state Exp;
branches;
next	1.6;

1.6
date	2000.11.13.22.39.51;	author leonardr;	state Exp;
branches;
next	1.5;

1.5
date	2000.11.13.17.35.17;	author leonardr;	state Exp;
branches;
next	1.4;

1.4
date	2000.11.12.22.57.31;	author dlr;	state Exp;
branches;
next	1.3;

1.3
date	2000.09.29.19.56.36;	author dlr;	state Exp;
branches;
next	1.2;

1.2
date	2000.09.29.19.55.46;	author dlr;	state Exp;
branches;
next	1.1;

1.1
date	2000.09.29.01.42.45;	author dlr;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2000.11.12.21.15.08;	author dlr;	state Exp;
branches;
next	;

1.14.2.1
date	2001.01.28.01.02.17;	author dlr;	state dead;
branches;
next	;


desc
@@


1.15
log
@delete stuff from the head which is obsolete in the branch (more changes
are still needed for a clean compile)
@
text
@/* ================================================================
 * Copyright (c) 2000 CollabNet.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if
 * any, must include the following acknowlegement: "This product includes
 * software developed by CollabNet (http://www.collab.net/)."
 * Alternately, this acknowlegement may appear in the software itself, if
 * and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The hosted project names must not be used to endorse or promote
 * products derived from this software without prior written
 * permission. For written permission, please contact info@@collab.net.
 * 
 * 5. Products derived from this software may not use the "Tigris" name
 * nor may "Tigris" appear in their names without prior written
 * permission of CollabNet.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by many
 * individuals on behalf of CollabNet.
 */


package org.tigris.helm.database;

import java.sql.*;
import java.util.*;

import com.workingdogs.village.*;

import org.webmacro.util.Log;

import org.joist.database.*;
import org.tigris.helm.DoesNotExist;
import org.tigris.helm.database.*;
import org.tigris.helm.domain.User;
import org.tigris.helm.project.Project;
import org.tigris.helm.tool.*;
import org.tigris.helm.security.AccessControlList;

/**
 * This class associates base projects with composite projects (which
 * represent groups of projects.)  
 *
 * @@author <a href="mailto:leonardr@@collab.net">Leonard Richardson</a>
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 * @@version $Id: ProjectProjectGroupManager.java,v 1.14 2001/01/26 18:29:00 edk Exp $
 */

public class ProjectProjectGroupManager extends CompositeManager
{
    /**
     * Open the log file.
     */
    private static Log log = new Log("prjGrpMgr", "ProjectProjectGroupManager");

    /**
     * The name of the table that this class manages.
     */
    public static final String TABLE_NAME = "HELM_PROJECT_PROJECTGROUP";

    /**
     * A table field name.
     */
    public static final String PROJECT_ID = "PROJECT_ID";

    /**
     * A table field name.
     */
    public static final String PROJECT_GROUP_ID = "PROJECT_GROUP_ID";

    /**
     * The values which indicate that the record is a base unit.
     */
    private static final String[] BASE_VALUES = { ProjectType.REGULAR };

    /**
     * The values which indicate that the record is a composite.
     */
    private static final String[] COMPOSITE_VALUES = { ProjectType.GROUP, 
                                                       ProjectType.CATEGORY,
                                                       ProjectType.DOMAIN,
                                                       ProjectType.HOST };

    /**
     * Creates a new instance.
     *
     * @@param dataMgr The associated manager.
     */
    public ProjectProjectGroupManager (DataManager dataMgr)
    {
        super(dataMgr, PROJECT_ID, PROJECT_GROUP_ID, 
              ProjectManager.TABLE_NAME, TABLE_NAME, 
              ProjectManager.PROJECT_TYPE, BASE_VALUES, COMPOSITE_VALUES);
    }

    public DataSet getProjectsForGroup(Connection connection, 
                                       String groupProjectID)
        throws DataSetException, SQLException
    {
        return getBasesForComposite(connection, groupProjectID);
    }

    public DataSet getGroupsForProject(Connection connection, 
                                       String baseProjectID)
        throws DataSetException, SQLException
    {
        return getCompositesForBase(connection, baseProjectID);
    }

    /**
     * Associates a project with a project group, and makes sure the
     * people who have roles in that project group get Issuezilla
     * accounts in the project.
     */
    public void addProjectToGroup(Connection connection, String baseProjectID, 
                                  String groupProjectID)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        addBaseToComposite(connection, baseProjectID, groupProjectID);
    }

    /**
     * Removes a project from a group, deleting all the Issuezilla accounts
     * users got in that project by virtue of belonging to that group.
     */
    public void removeProjectFromGroup(Connection connection, 
                                       String baseProjectID, 
                                       String groupProjectID)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        removeBaseFromComposite(connection, baseProjectID, groupProjectID);
    }
}
@


1.14
log
@readding all the files as part of the process of returning to the way
things were as of tuesday
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.10 2000/12/02 01:45:41 leonardr Exp $
@


1.14.2.1
log
@Porting to the Turbine Peer system.  -dlr and leonardr
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.14 2001/01/26 18:29:00 edk Exp $
@


1.13
log
@revert this stuff to its state as of 2001/01/24 12:42:00 GMT -- with
the following exceptions, which have some different modifications so
they'll work with changes which have happened in joist:

ProjectNewsEdit.java
SkinManager.java
SkinStyleElementValueManager.java
StyleElementManager.java
StyleManager.java

it compiles.  i dunno if it works, though.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.12 2001/01/24 21:41:48 leonardr Exp $
d121 3
a123 2
    public DataSet getProjectsForGroup(String groupProjectID)
        throws DBException
d125 1
a125 1
        return getBasesForComposite(groupProjectID);
d128 3
a130 2
    public DataSet getGroupsForProject(String baseProjectID)
        throws DBException
d132 1
a132 1
        return getCompositesForBase(baseProjectID);
d136 8
a143 4
     * Associates a project with a project group. Does not run scripts.
     */
    public void addProjectToGroup(String baseProjectID, String groupProjectID)
        throws DBException
d145 1
a145 1
        addBaseToComposite(baseProjectID, groupProjectID);
d149 2
a150 1
     * Removes a project from a group. Does not run scripts.
d152 2
a153 1
    public void removeProjectFromGroup(String baseProjectID, 
d155 2
a156 1
        throws DBException
d158 1
a158 1
        removeBaseFromComposite(baseProjectID, groupProjectID);
@


1.12
log
@Ported UserManager and RoleManager to Helm. Started moving other TableManagers toward a grab-connection-on-demand model. Massive breakage ensues. dlr and I are working on it.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.11 2001/01/24 20:42:46 dlr Exp $
@


1.11
log
@Making use of DBException.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.10 2000/12/02 01:45:41 leonardr Exp $
d121 1
a121 2
    public DataSet getProjectsForGroup(Connection connection, 
                                       String groupProjectID)
d124 1
a124 1
        return getBasesForComposite(connection, groupProjectID);
d127 1
a127 2
    public DataSet getGroupsForProject(Connection connection, 
                                       String baseProjectID)
d130 1
a130 1
        return getCompositesForBase(connection, baseProjectID);
d134 4
a137 7
     * Associates a project with a project group, and makes sure the
     * people who have roles in that project group get Issuezilla
     * accounts in the project.
     */
    public void addProjectToGroup(Connection connection, String baseProjectID, 
                                  String groupProjectID)
        throws DoesNotExist, DBException
d139 1
a139 1
        addBaseToComposite(connection, baseProjectID, groupProjectID);
d143 1
a143 2
     * Removes a project from a group, deleting all the Issuezilla accounts
     * users got in that project by virtue of belonging to that group.
d145 1
a145 2
    public void removeProjectFromGroup(Connection connection, 
                                       String baseProjectID, 
d147 1
a147 1
        throws DoesNotExist, DBException
d149 1
a149 1
        removeBaseFromComposite(connection, baseProjectID, groupProjectID);
@


1.10
log
@Changes to fix horrible mistakes in removing projects from project groups, among other things.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.9 2000/11/29 19:59:33 leonardr Exp $
d123 1
a123 1
        throws DataSetException, SQLException
d130 1
a130 1
        throws DataSetException, SQLException
d142 1
a142 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
d154 1
a154 2
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
@


1.9
log
@All project group activity now goes through the ProjectGroup object.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.8 2000/11/20 20:07:32 leonardr Exp $
d126 7
@


1.8
log
@Initial run at ProjectGroup business object.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.7 2000/11/17 00:29:21 leonardr Exp $
a137 1
        DataManager dMgr = getDataManager();
a138 4
        AccessControlList.buildProjectGroups(connection, dMgr);

        runScriptsForProjectGroup(connection, baseProjectID, groupProjectID,
                                  "Add");
a150 2
        DataManager dMgr = getDataManager();

a151 74
        AccessControlList.buildProjectGroups(connection, dMgr);

        runScriptsForProjectGroup(connection, baseProjectID, groupProjectID,
                                  "Delete");
    }

    /**
     * Removes a project from all its groups.
     */
    public void removeProjectFromGroups(Connection connection, 
                                        String baseProjectID)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        DataManager dMgr = getDataManager();

        //Get a list of groups.
        DataSet groups = getCompositesForBase(connection, baseProjectID);

        //Remove the project bindings ot the groups.
        removeBaseFromComposites(connection, baseProjectID);
        AccessControlList.buildProjectGroups(connection, dMgr);
        
        //Remove the users from Issuezilla.
        for (int i = 0; i < groups.size(); i++)
        {
            String groupProjectID = 
                groups.getRecord(i).getValue(PROJECT_GROUP_ID).toString();
            runScriptsForProjectGroup(connection, baseProjectID, 
                                      groupProjectID, "Delete");

        }
    }

    public void runScriptsForProjectGroup(Connection connection,
                                          String baseProjectID,
                                          String groupProjectID,
                                          String mode)
        throws SQLException, DataSetException, JoistDatabaseException,
               DoesNotExist
    {
        DataManager dMgr = getDataManager();
        ArrayList affectedUsers = new ArrayList();
        ArrayList affectedProjects = new ArrayList();

        UserRoleProjectManager urpMgr = (UserRoleProjectManager)
            dMgr.getManager("org.tigris.helm.database.UserRoleProjectManager");
        
        log.info("!!! Running scripts in " + mode + " mode.");
        //Only the base project is affected.
        Project project = new Project(connection, dMgr, baseProjectID);
        affectedProjects.add(project);
        log.info("!!! Project " + project.getName() + " is affected.");
        log.info("!!! GroupProjectID: " + groupProjectID);

        //All users with a role in the composite project are affected.
        DataSet users = urpMgr.getUsersForProject(connection, groupProjectID,
                                                  Boolean.TRUE);
        for (int i = 0; i < users.size(); i++)
        {
            User user = new User(connection, dMgr, users.getRecord(i));
            log.info("!!! User " + user.getName() + " is affected.");
            affectedUsers.add(user);
        }
        
        if (affectedUsers.size() > 0 && affectedProjects.size() > 0)
        {
            if (mode.equals("Add"))
            {
                TigrisUpdate.findNewMembers(affectedUsers, affectedProjects);
            } else {
                TigrisUpdate.findExMembers(affectedUsers, affectedProjects);
            }
        }
@


1.7
log
@Made the TigrisUpdate stuff saner with the use of business objects.
@
text
@d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.6 2000/11/13 22:39:51 leonardr Exp $
d79 1
a79 1
    private static Log log = new Log("prjGrpMgr", "ProjectProjectGrouPManager");
d119 7
@


1.6
log
@Permission checking bugfixes; one more big one on the way.
@
text
@d58 1
d60 2
d71 1
a71 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.5 2000/11/13 17:35:17 leonardr Exp $
d129 1
a129 1
               UpdateException
d147 1
a147 1
               UpdateException
d164 1
a164 1
               UpdateException
d190 2
a191 1
      throws SQLException, DataSetException, UpdateException, JoistDatabaseException
d200 1
d202 5
a206 3
        affectedProjects.add
            (TigrisUpdate.getProjectInfo(dMgr, connection, baseProjectID));
        
d212 3
a214 4
            Record user = users.getRecord(i);
            affectedUsers.add(TigrisUpdate.getUserInfo
                              (getDataManager(), connection, 
                               users.getRecord(i)));
@


1.5
log
@Made project deletion more consistent.
@
text
@d68 1
a68 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.4 2000/11/12 22:57:31 dlr Exp $
a128 1

@


1.4
log
@Resolved merge conflicts.
@
text
@d68 1
a68 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.1.1.1 2000/11/12 21:15:08 dlr Exp $
d154 28
@


1.3
log
@Corrected log id.
@
text
@d17 1
a17 1
 * software developed by Collab.Net (http://www.Collab.Net/)."
d27 1
a27 1
 * permission of Collab.Net.
d32 1
a32 1
 * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
d44 1
a44 1
 * individuals on behalf of Collab.Net.
d47 1
d50 1
a51 1
import java.sql.*;
d53 1
a53 2
import org.webmacro.util.*;
import org.webmacro.servlet.*;
d55 1
a55 1
import com.workingdogs.village.*;
d58 3
a60 1
import org.joist.util.*;
d63 2
a64 1
 * Manages one or more database table.
d66 1
d68 1
a68 3
 * @@version $Id: ProjectProjectGroupManager.java,v 1.2 2000/09/29 19:55:46 dlr Exp $
 *
 * Copyright (c) 2000 CollabNet, Inc.
d71 1
a71 1
public class ProjectProjectGroupManager extends TableManager
d73 32
a104 2
    private static Log log = new Log("ppgMgr", "ProjectProjectGroupManager");
    private static boolean debug = true;
d107 1
a107 1
     * Instantiates a new instance.
d109 13
a121 1
     * @@param	dataMgr  A variable of type DataManager
d123 38
a160 1
    public ProjectProjectGroupManager(DataManager dataMgr)
d162 31
a192 1
        super(dataMgr);
@


1.2
log
@Collab.Net --> CollabNet in copyright.
@
text
@d64 1
a64 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.1 2000/09/29 01:42:45 dlr Exp $
d71 1
a71 1
    private static Log log = new Log("rpsmMgr", "ProjectProjectGroupManager");
@


1.1
log
@Table manager stubs for the new Helm permission system.
@
text
@d2 1
a2 1
 * Copyright (c) 2000 Collab.Net.  All rights reserved.
d64 1
a64 1
 * @@version $Id: $
d66 1
a66 1
 * Copyright (c) 2000 Collab.Net, Inc.
@


1.1.1.1
log
@Merging newhelm tree into helm, as per IZ issue #557.  Previous major version of helm is tagged TIGRIS_NOV_11_2000.
@
text
@d2 1
a2 1
 * Copyright (c) 2000 CollabNet.  All rights reserved.
d17 1
a17 1
 * software developed by CollabNet (http://www.collab.net/)."
d27 1
a27 1
 * permission of CollabNet.
d32 1
a32 1
 * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
d44 1
a44 1
 * individuals on behalf of CollabNet.
a46 1

d49 1
d51 3
a53 1
import java.util.*;
a56 2
import org.webmacro.util.Log;

d58 1
a58 3
import org.tigris.helm.database.*;
import org.tigris.helm.tool.*;
import org.tigris.helm.security.AccessControlList;
d61 1
a61 2
 * This class associates base projects with composite projects (which
 * represent groups of projects.)  
a62 1
 * @@author <a href="mailto:leonardr@@collab.net">Leonard Richardson</a>
d64 3
a66 1
 * @@version $Id: ProjectProjectGroupManager.java,v 1.17 2000/11/08 22:01:50 leonardr Exp $
d69 1
a69 1
public class ProjectProjectGroupManager extends CompositeManager
d71 2
a72 32
    /**
     * Open the log file.
     */
    private static Log log = new Log("prjGrpMgr", "ProjectProjectGrouPManager");

    /**
     * The name of the table that this class manages.
     */
    public static final String TABLE_NAME = "HELM_PROJECT_PROJECTGROUP";

    /**
     * A table field name.
     */
    public static final String PROJECT_ID = "PROJECT_ID";

    /**
     * A table field name.
     */
    public static final String PROJECT_GROUP_ID = "PROJECT_GROUP_ID";

    /**
     * The values which indicate that the record is a base unit.
     */
    private static final String[] BASE_VALUES = { ProjectType.REGULAR };

    /**
     * The values which indicate that the record is a composite.
     */
    private static final String[] COMPOSITE_VALUES = { ProjectType.GROUP, 
                                                       ProjectType.CATEGORY,
                                                       ProjectType.DOMAIN,
                                                       ProjectType.HOST };
d75 1
a75 1
     * Creates a new instance.
d77 1
a77 13
     * @@param dataMgr The associated manager.
     */
    public ProjectProjectGroupManager (DataManager dataMgr)
    {
        super(dataMgr, PROJECT_ID, PROJECT_GROUP_ID, 
              ProjectManager.TABLE_NAME, TABLE_NAME, 
              ProjectManager.PROJECT_TYPE, BASE_VALUES, COMPOSITE_VALUES);
    }

    /**
     * Associates a project with a project group, and makes sure the
     * people who have roles in that project group get Issuezilla
     * accounts in the project.
d79 1
a79 38
    public void addProjectToGroup(Connection connection, String baseProjectID, 
                                  String groupProjectID)
        throws SQLException, DataSetException, JoistDatabaseException,
               UpdateException
    {
        DataManager dMgr = getDataManager();

        addBaseToComposite(connection, baseProjectID, groupProjectID);
        AccessControlList.buildProjectGroups(connection, dMgr);

        runScriptsForProjectGroup(connection, baseProjectID, groupProjectID,
                                  "Add");
    }

    /**
     * Removes a project from a group, deleting all the Issuezilla accounts
     * users got in that project by virtue of belonging to that group.
     */
    public void removeProjectFromGroup(Connection connection, 
                                       String baseProjectID, 
                                       String groupProjectID)
        throws SQLException, DataSetException, JoistDatabaseException,
               UpdateException
    {
        DataManager dMgr = getDataManager();

        removeBaseFromComposite(connection, baseProjectID, groupProjectID);
        AccessControlList.buildProjectGroups(connection, dMgr);

        runScriptsForProjectGroup(connection, baseProjectID, groupProjectID,
                                  "Delete");
    }

    public void runScriptsForProjectGroup(Connection connection,
                                          String baseProjectID,
                                          String groupProjectID,
                                          String mode)
      throws SQLException, DataSetException, UpdateException, JoistDatabaseException
d81 1
a81 31
        DataManager dMgr = getDataManager();
        ArrayList affectedUsers = new ArrayList();
        ArrayList affectedProjects = new ArrayList();

        UserRoleProjectManager urpMgr = (UserRoleProjectManager)
            dMgr.getManager("org.tigris.helm.database.UserRoleProjectManager");
        
        //Only the base project is affected.
        affectedProjects.add
            (TigrisUpdate.getProjectInfo(dMgr, connection, baseProjectID));
        
        //All users with a role in the composite project are affected.
        DataSet users = urpMgr.getUsersForProject(connection, groupProjectID,
                                                  Boolean.TRUE);
        for (int i = 0; i < users.size(); i++)
        {
            Record user = users.getRecord(i);
            affectedUsers.add(TigrisUpdate.getUserInfo
                              (getDataManager(), connection, 
                               users.getRecord(i)));
        }
        
        if (affectedUsers.size() > 0 && affectedProjects.size() > 0)
        {
            if (mode.equals("Add"))
            {
                TigrisUpdate.findNewMembers(affectedUsers, affectedProjects);
            } else {
                TigrisUpdate.findExMembers(affectedUsers, affectedProjects);
            }
        }
@


