CProxyAction.java

  1. /*
  2.  * @cond LICENSE
  3.  * ######################################################################################
  4.  * # LGPL License                                                                       #
  5.  * #                                                                                    #
  6.  * # This file is part of the LightJason AgentSpeak(L++)                                #
  7.  * # Copyright (c) 2015-19, LightJason (info@lightjason.org)                            #
  8.  * # This program is free software: you can redistribute it and/or modify               #
  9.  * # it under the terms of the GNU Lesser General Public License as                     #
  10.  * # published by the Free Software Foundation, either version 3 of the                 #
  11.  * # License, or (at your option) any later version.                                    #
  12.  * #                                                                                    #
  13.  * # This program is distributed in the hope that it will be useful,                    #
  14.  * # but WITHOUT ANY WARRANTY; without even the implied warranty of                     #
  15.  * # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                      #
  16.  * # GNU Lesser General Public License for more details.                                #
  17.  * #                                                                                    #
  18.  * # You should have received a copy of the GNU Lesser General Public License           #
  19.  * # along with this program. If not, see http://www.gnu.org/licenses/                  #
  20.  * ######################################################################################
  21.  * @endcond
  22.  */

  23. package org.lightjason.agentspeak.language.execution.action;

  24. import org.apache.commons.lang3.StringUtils;
  25. import org.lightjason.agentspeak.action.IAction;
  26. import org.lightjason.agentspeak.common.IPath;
  27. import org.lightjason.agentspeak.error.CIllegalArgumentException;
  28. import org.lightjason.agentspeak.language.CCommon;
  29. import org.lightjason.agentspeak.language.ILiteral;
  30. import org.lightjason.agentspeak.language.ITerm;
  31. import org.lightjason.agentspeak.language.execution.IContext;
  32. import org.lightjason.agentspeak.language.execution.IExecution;
  33. import org.lightjason.agentspeak.language.fuzzy.CFuzzyValue;
  34. import org.lightjason.agentspeak.language.fuzzy.IFuzzyValue;
  35. import org.lightjason.agentspeak.language.variable.IVariable;

  36. import javax.annotation.Nonnull;
  37. import java.text.MessageFormat;
  38. import java.util.Collection;
  39. import java.util.Collections;
  40. import java.util.LinkedList;
  41. import java.util.List;
  42. import java.util.Map;
  43. import java.util.Objects;
  44. import java.util.stream.Collectors;
  45. import java.util.stream.IntStream;
  46. import java.util.stream.Stream;


  47. /**
  48.  * proxy action to encapsulate all actions
  49.  */
  50. public final class CProxyAction implements IExecution
  51. {
  52.     /**
  53.      * serial id
  54.      */
  55.     private static final long serialVersionUID = 4799005052331053271L;
  56.     /**
  57.      * execution
  58.      */
  59.     private final IExecution m_execution;

  60.     /**
  61.      * ctor
  62.      *
  63.      * @param p_actions actions definition
  64.      * @param p_literal literal
  65.      */
  66.     public CProxyAction( @Nonnull final Map<IPath, IAction> p_actions, @Nonnull final ILiteral p_literal )
  67.     {
  68.         m_execution = new CActionWrapper( p_literal, p_actions );
  69.     }

  70.     @Nonnull
  71.     @Override
  72.     public final IFuzzyValue<Boolean> execute( final boolean p_parallel, @Nonnull final IContext p_context,
  73.                                                @Nonnull final List<ITerm> p_argument, @Nonnull final List<ITerm> p_return
  74.     )
  75.     {
  76.         return m_execution.execute( p_parallel, p_context, p_argument, p_return );
  77.     }

  78.     @Nonnull
  79.     @Override
  80.     public final Stream<IVariable<?>> variables()
  81.     {
  82.         return m_execution.variables();
  83.     }

  84.     @Override
  85.     public final String toString()
  86.     {
  87.         return MessageFormat.format( "{0}", m_execution );
  88.     }

  89.     /**
  90.      * inner class for encapsulating term values (variable / raw terms)
  91.      */
  92.     private static class CTermWrapper<T extends ITerm> implements IExecution
  93.     {
  94.         /**
  95.          * serial id
  96.          */
  97.         private static final long serialVersionUID = 6984535096829821628L;
  98.         /**
  99.          * term value
  100.          */
  101.         private final T m_value;

  102.         /**
  103.          * ctor
  104.          *
  105.          * @param p_value any static term
  106.          */
  107.         CTermWrapper( @Nonnull final T p_value )
  108.         {
  109.             m_value = p_value;
  110.         }

  111.         @Override
  112.         public final int hashCode()
  113.         {
  114.             return m_value.hashCode();
  115.         }

  116.         @Override
  117.         public final String toString()
  118.         {
  119.             return MessageFormat.format( "{0}", m_value );
  120.         }

  121.         @Override
  122.         public final boolean equals( final Object p_object )
  123.         {
  124.             return ( p_object instanceof IExecution ) && ( this.hashCode() == p_object.hashCode() );
  125.         }

  126.         @Nonnull
  127.         @Override
  128.         public final IFuzzyValue<Boolean> execute( final boolean p_parallel, @Nonnull final IContext p_context,
  129.                                                    @Nonnull final List<ITerm> p_argument, @Nonnull final List<ITerm> p_return
  130.         )
  131.         {
  132.             p_return.add( m_value );
  133.             return CFuzzyValue.from( true );
  134.         }

  135.         @Nonnull
  136.         @Override
  137.         public final Stream<IVariable<?>> variables()
  138.         {
  139.             return this.getVariableSet( m_value );
  140.         }

  141.         /**
  142.          * returns a variable set based on the generic type
  143.          *
  144.          * @param p_value term type
  145.          * @return variable set (empty)
  146.          */
  147.         @Nonnull
  148.         private Stream<IVariable<?>> getVariableSet( final T p_value )
  149.         {
  150.             return Stream.<IVariable<?>>empty();
  151.         }
  152.     }

  153.     /**
  154.      * inner class for encapsulating action execution
  155.      *
  156.      * @warning execution must run variable repacing before action calling
  157.      */
  158.     private static class CActionWrapper implements IExecution
  159.     {
  160.         /**
  161.          * serial id
  162.          */
  163.         private static final long serialVersionUID = 5531271525053969711L;
  164.         /**
  165.          * parallel execution flag
  166.          */
  167.         private final boolean m_parallel;
  168.         /**
  169.          * action
  170.          */
  171.         private final IAction m_action;
  172.         /**
  173.          * arguments as map with index for prevent
  174.          * result order on parallel execution
  175.          */
  176.         private final Map<Integer, IExecution> m_arguments;


  177.         /**
  178.          * ctor
  179.          *
  180.          * @param p_literal action literal
  181.          * @param p_actions actions
  182.          */
  183.         CActionWrapper( @Nonnull final ILiteral p_literal, @Nonnull final Map<IPath, IAction> p_actions )
  184.         {
  185.             // check parallel and inner execution
  186.             m_parallel = p_literal.hasAt();


  187.             // resolve action
  188.             m_action = p_actions.get( p_literal.fqnfunctor() );
  189.             if ( Objects.isNull( m_action ) )
  190.                 throw new CIllegalArgumentException( org.lightjason.agentspeak.common.CCommon.languagestring( this, "actionunknown", p_literal ) );

  191.             // check number of arguments and add action to the score cache
  192.             if ( p_literal.orderedvalues().count() < m_action.minimalArgumentNumber() )
  193.                 throw new CIllegalArgumentException(
  194.                     org.lightjason.agentspeak.common.CCommon.languagestring( this, "argumentnumber", p_literal, m_action.minimalArgumentNumber() ) );

  195.             // resolve action arguments
  196.             m_arguments = Collections.unmodifiableMap( this.createSubExecutions( p_literal.orderedvalues().collect( Collectors.toList() ), p_actions ) );
  197.         }

  198.         @Override
  199.         public final int hashCode()
  200.         {
  201.             return m_action.hashCode() + m_arguments.hashCode();
  202.         }

  203.         @Override
  204.         public final String toString()
  205.         {
  206.             return MessageFormat.format( "{0}({1})", m_action, StringUtils.join( m_arguments.values(), ", " ) );
  207.         }

  208.         @Override
  209.         public final boolean equals( final Object p_object )
  210.         {
  211.             return ( p_object instanceof IExecution ) && ( this.hashCode() == p_object.hashCode() );
  212.         }

  213.         @Nonnull
  214.         @Override
  215.         public IFuzzyValue<Boolean> execute( final boolean p_parallel, @Nonnull final IContext p_context,
  216.                                              @Nonnull final List<ITerm> p_argument, @Nonnull final List<ITerm> p_return
  217.         )
  218.         {
  219.             return m_action.execute(
  220.                 m_parallel, p_context,
  221.                 this.subexecute( p_context, m_arguments ),
  222.                 p_return
  223.             );
  224.         }

  225.         @Nonnull
  226.         @Override
  227.         public final Stream<IVariable<?>> variables()
  228.         {
  229.             return m_action.variables();
  230.         }

  231.         /**
  232.          * builds the map of execution arguments
  233.          *
  234.          * @param p_elements collection with literal elements (term- / literal list of attributes & annotations)
  235.          * @param p_actions map with actions
  236.          * @return ordered execution structure
  237.          */
  238.         @Nonnull
  239.         private Map<Integer, IExecution> createSubExecutions( @Nonnull final Collection<? extends ITerm> p_elements,
  240.                                                               @Nonnull final Map<IPath, IAction> p_actions )
  241.         {
  242.             // convert collection to list and build map with indices
  243.             final List<? extends ITerm> l_elements = new LinkedList<>( p_elements );
  244.             return IntStream.range( 0, l_elements.size() )
  245.                             .boxed()
  246.                             .collect(
  247.                                 Collectors.toMap(
  248.                                     i -> i,
  249.                                     i ->
  250.                                     {
  251.                                         final ITerm l_term = l_elements.get( i );
  252.                                         return l_term instanceof ILiteral
  253.                                                ? new CActionWrapper( l_term.term(), p_actions )
  254.                                                : new CTermWrapper<>( l_term );
  255.                                     }
  256.                                 )
  257.                             );
  258.         }

  259.         /**
  260.          * execute inner structures
  261.          *
  262.          * @param p_context context structure
  263.          * @param p_execution map with execution elements
  264.          * @return return arguments of execution (flat list)
  265.          */
  266.         @Nonnull
  267.         private List<ITerm> subexecute( @Nonnull final IContext p_context, @Nonnull final Map<Integer, IExecution> p_execution )
  268.         {
  269.             return Collections.unmodifiableList( CCommon.replaceFromContext(
  270.                 p_context,
  271.                 ( m_parallel
  272.                   ? p_execution.entrySet().parallelStream()
  273.                   : p_execution.entrySet()
  274.                                .stream() )
  275.                                .flatMap( i ->
  276.                                {
  277.                                    final List<ITerm> l_return = new LinkedList<>();
  278.                                    i.getValue().execute( m_parallel, p_context, Collections.emptyList(), l_return );
  279.                                    return l_return.stream();
  280.                                } )
  281.                                .collect( Collectors.toList() )
  282.             ) );
  283.         }
  284.     }

  285. }