LightJason - AgentSpeak(L++)
CLiteral.java
Go to the documentation of this file.
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 
24 package org.lightjason.agentspeak.language;
25 
26 import com.google.common.base.Charsets;
27 import com.google.common.collect.ImmutableListMultimap;
28 import com.google.common.collect.ImmutableMultimap;
29 import com.google.common.collect.LinkedListMultimap;
30 import com.google.common.collect.Multimap;
31 import com.google.common.hash.Hasher;
38 import org.lightjason.agentspeak.grammar.TypeLexer;
39 import org.lightjason.agentspeak.grammar.TypeParser;
42 
43 import javax.annotation.Nonnull;
44 import javax.annotation.Nullable;
45 import java.io.ByteArrayInputStream;
46 import java.io.InputStream;
47 import java.nio.charset.Charset;
48 import java.text.MessageFormat;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Collection;
52 import java.util.Collections;
53 import java.util.List;
54 import java.util.Objects;
55 import java.util.stream.Collectors;
56 import java.util.stream.Stream;
57 
58 
64 public final class CLiteral implements ILiteral
65 {
69  private static final long serialVersionUID = -3253396471300120109L;
73  private static final String NEGATION = "~";
77  private static final String AT = "@";
81  private final ImmutableMultimap<IPath, ITerm> m_values;
85  private final List<ITerm> m_orderedvalues;
89  private final IPath m_functor;
93  private final boolean m_negated;
97  private final boolean m_at;
101  private final int m_hash;
105  private final int m_structurehash;
106 
107 
108 
117  public CLiteral( final boolean p_at, final boolean p_negated, @Nonnull final IPath p_functor, @Nonnull final Collection<ITerm> p_values )
118  {
119  m_at = p_at;
120  m_negated = p_negated;
121  // create a full copy of the functor, because concurrency modification
122  m_functor = new CPath( p_functor );
123 
124  // create immutable structures
125  if ( !p_values.isEmpty() )
126  {
127  final Multimap<IPath, ITerm> l_values = LinkedListMultimap.create();
128  p_values.forEach( i -> l_values.put( i.fqnfunctor(), i ) );
129  m_values = ImmutableListMultimap.copyOf( l_values );
130  m_orderedvalues = Collections.unmodifiableList( new ArrayList<>( p_values ) );
131  }
132  else
133  {
134  m_orderedvalues = Collections.emptyList();
135  m_values = ImmutableListMultimap.of();
136  }
137 
138  // calculates object hash value
139  final Hasher l_hasher = CCommon.getTermHashing();
140  l_hasher.putInt( m_functor.hashCode() );
141  l_hasher.putBoolean( m_negated );
142  l_hasher.putBoolean( m_at );
143  m_orderedvalues.forEach( i -> l_hasher.putInt( i.hashCode() ) );
144  m_hash = l_hasher.hash().asInt();
145 
146  // calculates the structure hash value of the value definition (need to start with value definition)
147  final Hasher l_valuehasher = CCommon.getTermHashing();
148  m_orderedvalues.forEach( i -> l_valuehasher.putInt( i.structurehash() ) );
149  l_valuehasher.putBoolean( m_negated );
150  l_valuehasher.putString( p_functor.path(), Charsets.UTF_8 );
151  m_structurehash = l_valuehasher.hash().asInt();
152  }
153 
161  public static ILiteral from( @Nonnull final String p_functor, @Nullable final ITerm... p_values )
162  {
163  return from(
164  p_functor,
165  ( Objects.isNull( p_values ) ) || ( p_values.length == 0 )
166  ? Collections.emptySet()
167  : Arrays.stream( p_values ).collect( Collectors.toList() )
168  );
169  }
170 
178  public static ILiteral from( @Nonnull final String p_functor, @Nonnull final Collection<ITerm> p_values )
179  {
180  return new CLiteral(
181  p_functor.contains( AT ), p_functor.contains( NEGATION ), CPath.from( p_functor.replace( AT, "" ).replace( NEGATION, "" ) ),
182  p_values
183  );
184  }
185 
193  public static ILiteral from( @Nonnull final String p_functor, @Nonnull final Stream<ITerm> p_values )
194  {
195  return from( p_functor, p_values.collect( Collectors.toList() ) );
196  }
197 
205  public static ILiteral from( @Nonnull final IPath p_functor, @Nullable final ITerm... p_values )
206  {
207  return from( false, false, p_functor, p_values );
208  }
209 
217  public static ILiteral from( @Nonnull final IPath p_functor, @Nonnull final Stream<ITerm> p_values )
218  {
219  return from( false, false, p_functor, p_values );
220  }
221 
231  public static ILiteral from( final boolean p_at, final boolean p_negated, @Nonnull final IPath p_functor, @Nullable final ITerm... p_values )
232  {
233  return from( p_at, p_negated, p_functor, ( Objects.isNull( p_values ) ) || ( p_values.length == 0 ) ? Stream.empty() : Arrays.stream( p_values ) );
234  }
235 
245  public static ILiteral from( final boolean p_at, final boolean p_negated, @Nonnull final IPath p_functor, @Nonnull final Stream<ITerm> p_values )
246  {
247  return new CLiteral( p_at, p_negated, p_functor, p_values.collect( Collectors.toList() ) );
248  }
249 
258  @Nonnull
259  public static ILiteral parse( @Nonnull final String p_literal ) throws Exception
260  {
261  return new CParser().parse( new ByteArrayInputStream( p_literal.getBytes( Charset.forName( "UTF-8" ) ) ) ).literal();
262  }
263 
264  @Nonnull
265  @Override
266  public final Stream<ITerm> values( @Nullable final IPath... p_path )
267  {
268  return ( Objects.isNull( p_path ) ) || ( p_path.length < 1 )
269  ? m_values.values().stream()
270  : p_path.length == 1
271  ? m_values.asMap().get( p_path[0] ).stream()
272  : m_values.asMap().get( p_path[0] ).stream()
273  .filter( i -> i instanceof ILiteral )
274  .flatMap( i -> ( (ILiteral) i ).values( Arrays.copyOfRange( p_path, 1, p_path.length ) ) );
275  }
276 
277  @Nonnull
278  @Override
279  public final Stream<ITerm> orderedvalues( @Nullable final IPath... p_path )
280  {
281  return ( Objects.isNull( p_path ) ) || ( p_path.length < 1 )
282  ? m_orderedvalues.stream().sequential()
283  : p_path.length == 1
284  ? m_orderedvalues.stream()
285  .filter( i -> i.fqnfunctor().equals( p_path[0] ) ).sequential()
286  : m_orderedvalues.stream()
287  .filter( i -> i.fqnfunctor().equals( p_path[0] ) )
288  .filter( i -> i instanceof ILiteral )
289  .map( ITerm::<ILiteral>raw )
290  .filter( Objects::nonNull )
291  .flatMap( i -> i.orderedvalues( Arrays.copyOfRange( p_path, 1, p_path.length ) ) );
292  }
293 
294  @Override
295  public final boolean emptyValues()
296  {
297  return m_values.isEmpty();
298  }
299 
300  @Override
301  public final int structurehash()
302  {
303  return m_structurehash;
304  }
305 
306  @Override
307  public final boolean negated()
308  {
309  return m_negated;
310  }
311 
312  @Override
313  public final boolean hasAt()
314  {
315  return m_at;
316  }
317 
318  @Override
319  public final boolean hasVariable()
320  {
321  return m_orderedvalues.parallelStream().anyMatch( ITerm::hasVariable );
322  }
323 
324  @Nonnull
325  @Override
326  public final ILiteral unify( @Nonnull final IContext p_context )
327  {
328  return new CLiteral(
329  m_at,
330  m_negated,
331  m_functor,
332  m_orderedvalues.stream()
333  .map( i ->
334  {
335  if ( i instanceof IVariable<?> )
336  {
337  final IVariable<?> l_variable = p_context.instancevariables().get( i.fqnfunctor() );
338  return ( Objects.isNull( l_variable ) ) || ( l_variable.allocated() ) ? CRawTerm.from( l_variable ) : l_variable;
339  }
340  if ( i instanceof ILiteral )
341  return ( (ILiteral) i ).unify( p_context );
342  return i;
343  } )
344  .collect( Collectors.toList() )
345  );
346  }
347 
348  @Nonnull
349  @Override
350  public final ILiteral allocate( @Nonnull final IContext p_context )
351  {
352  return new CLiteral(
353  m_at,
354  m_negated,
355  m_functor,
356  m_orderedvalues.stream()
357  .map( i ->
358  {
359  if ( i instanceof IVariable<?> )
360  {
361  final IVariable<?> l_variable = p_context.instancevariables().get( i.fqnfunctor() );
362  return Objects.isNull( l_variable )
363  ? CRawTerm.EMPTY
364  : l_variable;
365  }
366  if ( i instanceof ILiteral )
367  return ( (ILiteral) i ).unify( p_context );
368  return i;
369  } )
370  .collect( Collectors.toList() )
371  );
372  }
373 
374  @Nonnull
375  @Override
376  public final String functor()
377  {
378  return m_functor.suffix();
379  }
380 
381  @Nonnull
382  @Override
383  public final IPath functorpath()
384  {
385  return m_functor.subpath( 0, m_functor.size() - 1 );
386  }
387 
388  @Nonnull
389  @Override
390  public final IPath fqnfunctor()
391  {
392  return m_functor;
393  }
394 
395  @Nonnull
396  @Override
397  @SuppressWarnings( "unchecked" )
398  public final <T> T raw()
399  {
400  return (T) this;
401  }
402 
403  @Override
404  public final int hashCode()
405  {
406  return m_hash;
407  }
408 
409  @Override
410  public final boolean equals( final Object p_object )
411  {
412  return ( p_object instanceof ILiteral ) && ( this.hashCode() == p_object.hashCode() );
413  }
414 
415  @Nonnull
416  @Override
417  public final ILiteral shallowcopy( @Nullable final IPath... p_prefix )
418  {
419  return ( Objects.isNull( p_prefix ) ) || ( p_prefix.length == 0 )
420 
421  ? new CLiteral(
423  m_values.values()
424  )
425 
426  : new CLiteral(
427  m_at, m_negated, p_prefix[0].append( m_functor ),
428  m_values.values()
429  );
430  }
431 
432  @Nonnull
433  @Override
435  {
436  return new CLiteral(
438  m_values.values()
439  );
440  }
441 
442  @Override
443  public final String toString()
444  {
445  return MessageFormat.format( "{0}{1}{2}{3}", m_negated ? NEGATION : "", m_at ? AT : "", m_functor, m_orderedvalues );
446  }
447 
448  @Override
449  public final int compareTo( @Nonnull final ILiteral p_literal )
450  {
451  return Integer.compare( this.hashCode(), p_literal.hashCode() );
452  }
453 
454  @Nonnull
455  @Override
456  public final synchronized ITerm deepcopy( @Nullable final IPath... p_prefix )
457  {
458  return ( Objects.isNull( p_prefix ) ) || ( p_prefix.length == 0 )
459 
460  ?
461  new CLiteral(
463  m_values.values().stream().map( i -> i.deepcopy() ).collect( Collectors.toList() )
464  )
465 
466  :
467  new CLiteral(
468  m_at, m_negated, p_prefix[0].append( m_functor ),
469  m_values.values().stream().map( i -> i.deepcopy() ).collect( Collectors.toList() )
470  );
471  }
472 
473  @Nonnull
474  @Override
475  public final synchronized ITerm deepcopysuffix()
476  {
477  return new CLiteral(
479  m_values.values().stream().map( i -> i.deepcopy() ).collect( Collectors.toList() )
480  );
481  }
482 
483 
487  private static final class CParser extends IBaseParser<IASTVisitorType, TypeLexer, TypeParser>
488  {
489 
494  CParser() throws NoSuchMethodException
495  {
496  super( new CErrorListener() );
497  }
498 
499  @Nonnull
500  @Override
501  public final IASTVisitorType parse( @Nonnull final InputStream p_stream ) throws Exception
502  {
503  final IASTVisitorType l_visitor = new CASTVisitorType();
504  l_visitor.visit( this.parser( p_stream ).literal_type() );
505  return l_visitor;
506  }
507 
508  @Override
509  protected final Class<TypeLexer> lexerclass()
510  {
511  return TypeLexer.class;
512  }
513 
514  @Override
515  protected final Class<TypeParser> parserclass()
516  {
517  return TypeParser.class;
518  }
519  }
520 }
CLiteral(final boolean p_at, final boolean p_negated, @Nonnull final IPath p_functor, @Nonnull final Collection< ITerm > p_values)
ctor
Definition: CLiteral.java:117
final boolean hasAt()
returns if the literal has an @ prefix
Definition: CLiteral.java:313
final IPath m_functor
literals functor
Definition: CLiteral.java:89
IPath subpath(final int p_fromindex)
creates a path of the start index until the end
final boolean m_negated
negated option
Definition: CLiteral.java:93
final String functor()
returns the functor without path
Definition: CLiteral.java:376
final ImmutableMultimap< IPath, ITerm > m_values
literal values
Definition: CLiteral.java:81
final boolean m_at
@ prefix is set
Definition: CLiteral.java:97
static final String NEGATION
negation symbol
Definition: CLiteral.java:73
final boolean negated()
getter of the literal for the negation
Definition: CLiteral.java:307
final ILiteral unify( @Nonnull final IContext p_context)
unifies variables if exists
Definition: CLiteral.java:326
static IPath from( @Nonnull final String p_string)
factor method to build path
Definition: CPath.java:166
final synchronized ITerm deepcopysuffix()
Definition: CLiteral.java:475
class to create a path structure
Definition: CPath.java:53
static ILiteral from(final boolean p_at, final boolean p_negated, @Nonnull final IPath p_functor, @Nonnull final Stream< ITerm > p_values)
factory
Definition: CLiteral.java:245
static ILiteral from( @Nonnull final String p_functor, @Nonnull final Collection< ITerm > p_values)
factory
Definition: CLiteral.java:178
final Stream< ITerm > orderedvalues( @Nullable final IPath... p_path)
returns a stream over the ordered values in sequential ordering
Definition: CLiteral.java:279
final ILiteral allocate( @Nonnull final IContext p_context)
allocate all variables with the current context
Definition: CLiteral.java:350
final List< ITerm > m_orderedvalues
literal values as list
Definition: CLiteral.java:85
final int structurehash()
returns a hash value which defines a hash ove rthe structure
Definition: CLiteral.java:301
AntLR error lister to catch parser and lexer errors with individual error handling and language trans...
static final ITerm EMPTY
empty raw term
Definition: CRawTerm.java:50
execution context with local data
Definition: IContext.java:42
static ILiteral from( @Nonnull final IPath p_functor, @Nullable final ITerm... p_values)
factory
Definition: CLiteral.java:205
final Stream< ITerm > values( @Nullable final IPath... p_path)
Definition: CLiteral.java:266
Stream< String > stream()
stream over elements
final< T > T raw()
cast to any raw value type
Definition: CLiteral.java:398
final int m_structurehash
hash of the structure
Definition: CLiteral.java:105
final int compareTo( @Nonnull final ILiteral p_literal)
Definition: CLiteral.java:449
static ILiteral from( @Nonnull final IPath p_functor, @Nonnull final Stream< ITerm > p_values)
factory
Definition: CLiteral.java:217
final IPath functorpath()
returns the path of the functor
Definition: CLiteral.java:383
final boolean emptyValues()
check for empty values
Definition: CLiteral.java:295
final synchronized ITerm deepcopy( @Nullable final IPath... p_prefix)
Definition: CLiteral.java:456
final boolean hasVariable()
checks if the literal has variables
Definition: CLiteral.java:319
default generic literal class for agent beliefs a literal consists of a functor, an optional list of ...
Definition: CLiteral.java:64
final P parser( @Nonnull final InputStream p_stream)
returns a parser component
static final String AT
at symbol
Definition: CLiteral.java:77
static< N > CRawTerm< N > from(final N p_value)
factory for a raw term
Definition: CRawTerm.java:104
final IPath fqnfunctor()
returns the full-qualified functor with path and name
Definition: CLiteral.java:390
static ILiteral from(final boolean p_at, final boolean p_negated, @Nonnull final IPath p_functor, @Nullable final ITerm... p_values)
factory
Definition: CLiteral.java:231
static ILiteral parse( @Nonnull final String p_literal)
factory
Definition: CLiteral.java:259
static ILiteral from( @Nonnull final String p_functor, @Nonnull final Stream< ITerm > p_values)
stream factory
Definition: CLiteral.java:193
static ILiteral from( @Nonnull final String p_functor, @Nullable final ITerm... p_values)
factory
Definition: CLiteral.java:161
final ILiteral shallowcopy( @Nullable final IPath... p_prefix)
Definition: CLiteral.java:417
String suffix()
returns the last part of the path
final boolean equals(final Object p_object)
Definition: CLiteral.java:410
boolean hasVariable()
checks if the literal has variables
static final long serialVersionUID
serial id
Definition: CLiteral.java:69
int size()
returns the number of path elements
final IASTVisitorType parse( @Nonnull final InputStream p_stream)
Definition: CLiteral.java:501
term structure for simple datatypes
Definition: CRawTerm.java:45