DemandJspBean.java

/*
 * Copyright (c) 2002-2019, Mairie de Paris
 * 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
 *     and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *
 *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS 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 THE COPYRIGHT HOLDERS OR 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.
 *
 * License 1.0
 */
package fr.paris.lutece.plugins.appcenter.web;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import fr.paris.lutece.plugins.appcenter.business.Application;
import fr.paris.lutece.plugins.appcenter.business.ApplicationDatas;
import fr.paris.lutece.plugins.appcenter.business.ApplicationHome;
import fr.paris.lutece.plugins.appcenter.business.Demand;
import fr.paris.lutece.plugins.appcenter.business.DemandFilter;
import fr.paris.lutece.plugins.appcenter.business.DemandHome;
import fr.paris.lutece.plugins.appcenter.business.DemandType;
import fr.paris.lutece.plugins.appcenter.business.DemandTypeHome;
import fr.paris.lutece.plugins.appcenter.business.Environment;
import fr.paris.lutece.plugins.appcenter.service.DemandService;
import fr.paris.lutece.plugins.appcenter.service.DemandTypeService;
import fr.paris.lutece.plugins.appcenter.util.AppCenterUtils;
import fr.paris.lutece.plugins.workflowcore.business.state.State;
import fr.paris.lutece.plugins.workflowcore.business.state.StateFilter;
import fr.paris.lutece.plugins.workflowcore.service.state.IStateService;
import fr.paris.lutece.plugins.workflowcore.service.state.StateService;
import fr.paris.lutece.portal.service.content.XPageAppService;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.message.AdminMessage;
import fr.paris.lutece.portal.service.message.AdminMessageService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppException;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.workflow.WorkflowService;
import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
import fr.paris.lutece.portal.web.constants.Parameters;
import fr.paris.lutece.portal.web.xpages.XPageApplication;
import fr.paris.lutece.portal.web.xpages.XPageApplicationEntry;
import fr.paris.lutece.util.ReferenceItem;
import fr.paris.lutece.util.ReferenceList;
import fr.paris.lutece.util.sort.AttributeComparator;
import fr.paris.lutece.util.url.UrlItem;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Locale;
import java.util.Optional;

/**
 * This class provides the user interface to manage Demand features ( manage, create, modify, remove )
 */
@Controller( controllerJsp = "ManageDemands.jsp", controllerPath = "jsp/admin/plugins/appcenter/", right = "APPCENTER_MANAGEMENT" )
public class DemandJspBean extends ManageAppCenterJspBean
{
    // Templates
    private static final String TEMPLATE_MANAGE_DEMANDS = "/admin/plugins/appcenter/manage_demands.html";
    private static final String TEMPLATE_TASK_FORM = "/admin/plugins/appcenter/task_form.html";
    private static final String TEMPLATE_DEMAND_HISTORY = "/admin/plugins/appcenter/demand_history.html";

    // Parameters
    private static final String PARAMETER_ID_DEMAND = "id";
    private static final String PARAMETER_ID_ACTION = "id_action";

    // Properties for page titles
    private static final String PROPERTY_PAGE_TITLE_MANAGE_DEMANDS = "appcenter.manage_demands.pageTitle";
    private static final String PROPERTY_PAGE_TITLE_TASK_FORM = "appcenter.task_form.pageTitle";
    private static final String PROPERTY_PAGE_TITLE_DEMAND_HISTORY = "appcenter.demand_history.pageTitle";

    // Markers
    private static final String MARK_DEMAND_LIST = "demand_list";
    private static final String MARK_DEMAND = "demand";
    private static final String MARK_ID_ACTION = "id_action";
    private static final String MARK_APPLICATION = "application";
    private static final String MARK_DEMAND_TYPE_REF_LIST = "demand_type_ref_list";
    private static final String MARK_ENVIRONMENT_REF_LIST = "environment_ref_list";
    private static final String MARK_APPLICATION_REF_LIST = "application_ref_list";
    private static final String MARK_STATE_REF_LIST = "state_ref_list";
    private static final String MARK_DEMAND_FILTER = "demand_filter";

    private static final String MARK_TASK_FORM = "task_form";

    private static final String MARK_APPLICATION_MAP = "applications";
    private static final String MARK_STATES_MAP = "states";

    private static final String MARK_ACTIONS_MAP = "actions";
    private static final String MARK_HISTORY = "history";
    private static final String MARK_JSON_DATA = "json_data";
    private static final String JSP_MANAGE_DEMANDS = "jsp/admin/plugins/appcenter/ManageDemands.jsp";

    // Properties
    private static final String MESSAGE_CONFIRM_REMOVE_DEMAND = "appcenter.message.confirmRemoveDemand";

    // Views
    private static final String VIEW_MANAGE_DEMANDS = "manageDemands";
    private static final String VIEW_TASK_FORM = "taskForm";
    private static final String VIEW_HISTORY = "demandHistory";

    // Actions
    private static final String ACTION_PROCESS_ACTION = "processAction";
    private static final String ACTION_SAVE_TASK_FORM = "saveTaskForm";
    private static final String ACTION_FILTER_DEMAND = "filterDemands";
    private static final String ACTION_REMOVE_DEMAND = "removeDemand";
    private static final String ACTION_CONFIRM_REMOVE_DEMAND = "confirmRemoveDemand";

    // Constant
    private static final String CONSTANT_ID = "id";
    private static final String CONSTANT_LABEL_DEMAND_TYPE = "labelDemandType";
    private static final String CONSTANT_CODE_APPLICATION = "codeApplication";
    private static final String CONSTANT_NAME_APPLICATION = "nameApplication";
    private static final String CONSTANT_WORKFLOW_STATE = "workflowState";
    private static final String CONSTANT_ID_USER_FRONT = "idUserFront";
    private static final String CONSTANT_CREATION_DATE = "creationDate";

    // Infos
    private static final String INFO_DEMAND_REMOVED = "appcenter.info.demand.removed";

    // Errors
    private static final String ERROR_CANNOT_PROCESS_ACTION = "appcenter.error.demand.cannotProcessAction";

    // Sessions variable
    private DemandFilter _filter;
    private IStateService _stateService = SpringContextService.getBean( StateService.BEAN_SERVICE );

    private static final String STATE_IN_PROGRESS = "En cours";

    /**
     * Build the Manage View
     * 
     * @param request
     *            The HTTP request
     * @return The page
     */
    @View( value = VIEW_MANAGE_DEMANDS, defaultView = true )
    public String getManageDemands( HttpServletRequest request )
    {

        // Initialize the demand filter
        if ( _filter == null )
        {
            _filter = new DemandFilter( );

            // open demands filter default
            _filter.setHasState( true );
            _filter.setState( STATE_IN_PROGRESS );
        }

        List<Demand> listDemands = DemandHome.getDemandsListByFilter( _filter );
        int nIdWorkflow;

        Map<String, Application> mapApplications = new HashMap<>( );
        Map<String, State> mapStates = new HashMap<>( );
        Map<String, DemandType> mapDemandTypes = new HashMap<>( );

        Map<String, Collection<fr.paris.lutece.plugins.workflowcore.business.action.Action>> mapActions = new HashMap<>( );

        for ( Application app : ApplicationHome.getApplicationsList( ) )
        {
            mapApplications.put( Integer.toString( app.getId( ) ), app );
        }

        for ( DemandType demandType : DemandTypeHome.getDemandTypesList( ) )
        {
            mapDemandTypes.put( demandType.getIdDemandType( ), demandType );
        }

        for ( Demand demand : listDemands )
        {

            nIdWorkflow = DemandTypeService.getIdWorkflow( demand.getDemandType( ) );
            State state = WorkflowService.getInstance( ).getState( demand.getId( ), Demand.WORKFLOW_RESOURCE_TYPE, nIdWorkflow, -1 );
            mapStates.put( Integer.toString( demand.getId( ) ), state );

            Collection<fr.paris.lutece.plugins.workflowcore.business.action.Action> listAllActions = WorkflowService.getInstance( ).getActions( demand.getId( ),
                    Demand.WORKFLOW_RESOURCE_TYPE, nIdWorkflow, getUser( ) );
            Collection<fr.paris.lutece.plugins.workflowcore.business.action.Action> listActions = new ArrayList<>( );

            for (fr.paris.lutece.plugins.workflowcore.business.action.Action action : listAllActions )
            {
                if ( !action.isAutomaticState( ) )
                {
                    listActions.add( action );
                }
            }

            mapActions.put( Integer.toString( demand.getId( ) ), listActions );

        }

        Comparator<ReferenceItem> comparator = Comparator.comparing( ( ReferenceItem x ) -> x.getName( ) );

        // Construct demand type ref list
        ReferenceList demandTypeRefList = ReferenceList.convert( mapDemandTypes.values( ), "idDemandType", "label", false );

        // Filter demand list and demand type reference list by RBAC on demandType
        DemandTypeService.filterWithRBAC( listDemands, demandTypeRefList, getUser( ) );
        Collections.sort( demandTypeRefList, comparator );

        AppCenterUtils.addFirstItem( demandTypeRefList, request.getLocale( ) );

        // Construct envi ref list
        ReferenceList refListEnvi = ReferenceList.convert( Arrays.asList( Environment.values( ) ), "prefix", "labelKey", false );
        for ( ReferenceItem item : refListEnvi )
        {
            item.setName( I18nService.getLocalizedString( item.getName( ), request.getLocale( ) ) );
        }
        Collections.sort( refListEnvi, comparator );
        AppCenterUtils.addFirstItem( refListEnvi, request.getLocale( ) );

        // Construct application ref list
        ReferenceList applicationRefList = ReferenceList.convert( mapApplications.values( ), "id", "name", true );
        Collections.sort( applicationRefList, comparator );
        AppCenterUtils.addFirstItem( applicationRefList, request.getLocale( ) );

        // Construct application ref list
        ReferenceList stateRefList = new ReferenceList( );
        List<DemandType> demandTypeList = DemandTypeHome.getDemandTypesList( );
        for (DemandType demandType : demandTypeList )
        {
            if ( demandType.getIdWorkflow( ) != StateFilter.ALL_INT )
            {
                StateFilter stateFilter = new StateFilter( );
                stateFilter.setIdWorkflow( demandType.getIdWorkflow( ) );

                List<State> listState = _stateService.getListStateByFilter( stateFilter );
                for ( State state : listState )
                {
                    stateRefList.addItem( state.getName( ), state.getName( ) );
                }
            }
        }
        stateRefList = ReferenceList.convert( stateRefList.toMap( ) ); //filter duplicate
        Collections.sort( stateRefList, comparator );
        AppCenterUtils.addFirstItem( stateRefList, request.getLocale( ) );

        // SORT
        String strSortedAttributeName = request.getParameter( Parameters.SORTED_ATTRIBUTE_NAME );
        String strAscSort = null;

        if ( strSortedAttributeName != null )
        {
            strAscSort = request.getParameter( Parameters.SORTED_ASC );

            boolean bIsAscSort = Boolean.parseBoolean( strAscSort );

            if ( strSortedAttributeName.equals( CONSTANT_ID ) || strSortedAttributeName.equals( CONSTANT_ID_USER_FRONT )
                    || strSortedAttributeName.equals( CONSTANT_CREATION_DATE ) )
            {
                Collections.sort( listDemands, new AttributeComparator( strSortedAttributeName, bIsAscSort ) );
            }
            else
            {
                Comparator<Demand> c = null;

                if ( strSortedAttributeName.equals( CONSTANT_CODE_APPLICATION ) )
                {
                    c = Comparator.comparing( ( Demand x ) -> mapApplications.get( Integer.toString( x.getIdApplication( ) ) ).getCode( ) );
                }
                if ( strSortedAttributeName.equals( CONSTANT_NAME_APPLICATION ) )
                {
                    c = Comparator.comparing( ( Demand x ) -> mapApplications.get( Integer.toString( x.getIdApplication( ) ) ).getName( ) );
                }
                else
                    if ( strSortedAttributeName.equals( CONSTANT_LABEL_DEMAND_TYPE ) )
                    {
                        c = Comparator.comparing( ( Demand x ) -> mapDemandTypes.get( x.getIdDemandType( ) ).getLabel( ) );
                    }
                    else
                        if ( strSortedAttributeName.equals( CONSTANT_WORKFLOW_STATE ) )
                        {
                            c = Comparator.comparing( ( Demand x ) -> mapStates.get( Integer.toString( x.getId( ) ) ).getName( ) );
                        }

                if ( c != null )
                {
                    if ( bIsAscSort )
                    {
                        Collections.sort( listDemands, Collections.reverseOrder( c ) );
                    }
                    else
                    {
                        Collections.sort( listDemands, c );
                    }
                }
            }
        }

        UrlItem url = new UrlItem( JSP_MANAGE_DEMANDS );

        if ( strSortedAttributeName != null )
        {
            url.addParameter( Parameters.SORTED_ATTRIBUTE_NAME, strSortedAttributeName );
        }

        if ( strAscSort != null )
        {
            url.addParameter( Parameters.SORTED_ASC, strAscSort );
        }

        Map<String, Object> model = getPaginatedListModel( request, MARK_DEMAND_LIST, listDemands, url.getUrl( ) );

        model.put( MARK_DEMAND_TYPE_REF_LIST, demandTypeRefList );
        model.put( MARK_ENVIRONMENT_REF_LIST, refListEnvi );
        model.put( MARK_APPLICATION_REF_LIST, applicationRefList );
        model.put( MARK_STATE_REF_LIST, stateRefList );
        model.put( MARK_DEMAND_FILTER, _filter );
        model.put( MARK_APPLICATION_MAP, mapApplications );
        model.put( MARK_STATES_MAP, mapStates );
        model.put( MARK_ACTIONS_MAP, mapActions );

        return getPage( PROPERTY_PAGE_TITLE_MANAGE_DEMANDS, TEMPLATE_MANAGE_DEMANDS, model );
    }

    /**
     * Process the action of filtering demands; set the filter
     * 
     * @param request
     * @return The manage demands view
     */
    @Action( ACTION_FILTER_DEMAND )
    public String doFilterDemand( HttpServletRequest request )
    {
        _filter = DemandService.computeDemandFilter( request );
        return redirectView( request, VIEW_MANAGE_DEMANDS );
    }

    /**
     * Returns the task form associate to the workflow action
     *
     * @param request
     *            The Http request
     * @return The HTML form the task form associate to the workflow action
     */
    @View( VIEW_TASK_FORM )
    public String getTaskForm( HttpServletRequest request )
    {
        // Demand
        Demand demand = null;
        Integer nIdDemand = request.getParameter( PARAMETER_ID_DEMAND ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_DEMAND ) ) : null;
        Integer nIdAction = request.getParameter( PARAMETER_ID_ACTION ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_ACTION ) ) : null;

        if ( nIdAction == null || nIdDemand == null )
        {
            return redirectView( request, VIEW_MANAGE_DEMANDS );

        }

        demand = DemandHome.findByPrimaryKey( nIdDemand );

        // Aplication
        Application application = ApplicationHome.findByPrimaryKey( demand.getIdApplication( ) );

        String strHtmlTasksForm = WorkflowService.getInstance( )
                .getDisplayTasksForm( nIdDemand, Demand.WORKFLOW_RESOURCE_TYPE, nIdAction, request, getLocale( ) );

        Map<String, Object> model = getModel( );
        model.put( MARK_DEMAND, demand );
        model.put( MARK_APPLICATION, application );
        model.put( MARK_ID_ACTION, nIdAction );

        model.put( MARK_TASK_FORM, strHtmlTasksForm );

        return getPage( PROPERTY_PAGE_TITLE_TASK_FORM, TEMPLATE_TASK_FORM, model );
    }

    /**
     * Returns the task form associate to the workflow action
     *
     * @param request
     *            The Http request
     * @return The HTML form the task form associate to the workflow action
     */
    @View( VIEW_HISTORY )
    public String getViewHistory( HttpServletRequest request )
    {
        // Demand
        Demand demand = null;
        Integer nIdDemand = request.getParameter( PARAMETER_ID_DEMAND ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_DEMAND ) ) : null;

        demand = DemandHome.findByPrimaryKey( nIdDemand );
        Class demandClass = DemandTypeService.getClassByDemandTypeId( demand.getIdDemandType( ), DemandTypeHome.getDemandTypesList( ) );
        demand = DemandHome.findByPrimaryKey( nIdDemand, demandClass );
        int nIdWorkflow = DemandTypeService.getIdWorkflow( demand.getDemandType( ) );

        String strHistoryHtml = WorkflowService.getInstance( ).getDisplayDocumentHistory( demand.getId( ), Demand.WORKFLOW_RESOURCE_TYPE, nIdWorkflow, request,
                request.getLocale( ) );

        // Aplication
        Application application = ApplicationHome.findByPrimaryKey( demand.getIdApplication( ) );

        String strJsonData = DemandService.getPrettyPrintDemandData( demand );

        Map<String, Object> model = getModel( );
        model.put( MARK_DEMAND, demand );
        model.put( MARK_APPLICATION, application );
        model.put( MARK_HISTORY, strHistoryHtml );
        model.put( MARK_JSON_DATA, strJsonData );

        return getPage( PROPERTY_PAGE_TITLE_DEMAND_HISTORY, TEMPLATE_DEMAND_HISTORY, model );
    }

    /**
     * Process workflow action
     *
     * @param request
     *            The Http request
     * @return The Jsp URL of the process result
     */
    @Action( ACTION_PROCESS_ACTION )
    public String doProcessAction( HttpServletRequest request )
    {

        Integer nIdDemand = request.getParameter( PARAMETER_ID_DEMAND ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_DEMAND ) ) : null;
        Integer nIdAction = request.getParameter( PARAMETER_ID_ACTION ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_ACTION ) ) : null;

        if ( WorkflowService.getInstance( ).isDisplayTasksForm( nIdAction, getLocale( ) ) )
        {
            return redirect( request, VIEW_TASK_FORM, PARAMETER_ID_DEMAND, nIdDemand, PARAMETER_ID_ACTION, nIdAction );
        }

        WorkflowService.getInstance( ).doProcessAction( nIdDemand, Demand.WORKFLOW_RESOURCE_TYPE, nIdAction, -1, request, getLocale( ), true );

        return redirectView( request, VIEW_MANAGE_DEMANDS );
    }

    /**
     * Process workflow action
     *
     * @param request
     *            The Http request
     * @return The Jsp URL of the process result
     */
    @Action( ACTION_SAVE_TASK_FORM )
    public String doSaveTaskForm( HttpServletRequest request )
    {

        Integer nIdDemand = request.getParameter( PARAMETER_ID_DEMAND ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_DEMAND ) ) : null;
        Integer nIdAction = request.getParameter( PARAMETER_ID_ACTION ) != null ? Integer.parseInt( request.getParameter( PARAMETER_ID_ACTION ) ) : null;

        if ( WorkflowService.getInstance( ).canProcessAction( nIdDemand, Demand.WORKFLOW_RESOURCE_TYPE, nIdAction, -1, request, false ) )
        {

            try
            {
                String strError = WorkflowService.getInstance( )
                        .doSaveTasksForm( nIdDemand, Demand.WORKFLOW_RESOURCE_TYPE, nIdAction, -1, request, getLocale( ) );
                if ( strError != null )
                {
                    addError( strError );
                    return redirect( request, VIEW_TASK_FORM, PARAMETER_ID_DEMAND, nIdDemand, PARAMETER_ID_ACTION, nIdAction );
                }

            }
            catch( Exception e )
            {
                AppLogService.error( "Error processing action for demand '" + nIdDemand, e );
                addError( ERROR_CANNOT_PROCESS_ACTION, getLocale( ) );
            }

        }
        else
        {
            return redirectView( request, VIEW_TASK_FORM );
        }

        return redirectView( request, VIEW_MANAGE_DEMANDS );
    }

    /**
     * Manages the removal form of a application whose identifier is in the http request
     *
     * @param request
     *            The Http request
     * @return the html code to confirm
     */
    @Action( ACTION_CONFIRM_REMOVE_DEMAND )
    public String getConfirmRemoveDemand( HttpServletRequest request )
    {
        int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_DEMAND ) );
        UrlItem url = new UrlItem( getActionUrl( ACTION_REMOVE_DEMAND ) );
        url.addParameter( PARAMETER_ID_DEMAND, nId );

        String strMessageUrl = AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_DEMAND, url.getUrl( ), AdminMessage.TYPE_CONFIRMATION );

        return redirect( request, strMessageUrl );
    }

    /**
     * Handles the removal form of a demand
     *
     * @param request
     *            The Http request
     * @return the jsp URL to display the form to manage demands
     */
    @Action( ACTION_REMOVE_DEMAND )
    public String doRemoveDemand( HttpServletRequest request )
    {
        int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_DEMAND ) );
        DemandService.remove( nId );
        addInfo( INFO_DEMAND_REMOVED, getLocale( ) );

        return redirectView( request, VIEW_MANAGE_DEMANDS );
    }

    public static Class getClassApplicationDatasByDemandTypeKey( String strDemandTypeKey )
    {
        Collection<XPageApplicationEntry> listXPageApplicationEntry = XPageAppService.getXPageApplicationsList( );
        XPageApplication xPageApplication = null;

        for ( XPageApplicationEntry xPageApplicationEntry : listXPageApplicationEntry )
        {
            xPageApplication = XPageAppService.getApplicationInstance( xPageApplicationEntry );
            if ( xPageApplication instanceof AppCenterDemandXPage )
            {
                AppCenterDemandXPage appCenterDemandXPage = (AppCenterDemandXPage) xPageApplication;
                if ( appCenterDemandXPage.getDemandType( ) != null && appCenterDemandXPage.getDemandType( ).equals( strDemandTypeKey ) )
                {
                    return appCenterDemandXPage.getDatasClass( );
                }
            }
        }

        return null;
    }
}