All Downloads are FREE. Search and download functionalities are using the official Maven repository.

manifold.ext.rt.api.IListBacked Maven / Gradle / Ivy

There is a newer version: 2024.1.42
Show newest version
/*
 * Copyright (c) 2020 - Manifold Systems LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package manifold.ext.rt.api;

import manifold.ext.rt.RuntimeMethods;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * A {@link Structural} interface with only list methods can extend this interface and provide default
 * implementations of its methods and implement a compile-time proxy API to avoid the overhead runtime proxy
 * generation.
 * 

* See the {@code JsonListType}. */ public interface IListBacked extends List { /** * The {@link List} object used to store raw values corresponding with List methods. */ List getList(); /** * Finds declared type parameter of type extending IListBacked. *
interface Hobby extends IlistBacked<HobbyItem>
* Returns {@code HobbyItem} */ default Class getFinalComponentType() { Class[] interfaces = getClass().getInterfaces(); for( Class e : interfaces ) { for( Type iface : e.getGenericInterfaces() ) { if( iface instanceof ParameterizedType && List.class.isAssignableFrom( (Class)((ParameterizedType)iface).getRawType() ) ) { Type typeArg = ((ParameterizedType)iface).getActualTypeArguments()[0]; if( typeArg instanceof ParameterizedType ) { typeArg = ((ParameterizedType)typeArg).getRawType(); } if( typeArg instanceof Class ) { //noinspection unchecked return (Class)typeArg; } } } } throw new IllegalStateException(); } /* * Delegate to the wrapped List. */ default void coerceListToBindingValues() { List list = getList(); for( int i = 0; i < list.size(); i++ ) { Object e = list.get( i ); e = toBindingsValue( (T) e ); list.set( i, e ); } } default List coerceListToComplexValues() { return (List) getList().stream() .map( e -> coerce( e, getFinalComponentType() ) ) .collect( Collectors.toList() ); } default Object coerce( Object value, Class type ) { return RuntimeMethods.coerceFromBindingsValue( value, type ); } @Override default void replaceAll( UnaryOperator operator ) { getList().replaceAll( e -> toBindingsValue( operator.apply( (T) coerce( e, getFinalComponentType() ) ) ) ); } @Override default void sort( Comparator c ) { List cList = coerceListToComplexValues(); cList.sort( c ); List bList = toBindings( cList ); for( int i = 0; i < bList.size(); i++ ) { getList().set( i, bList.get( i ) ); } } @Override default Spliterator spliterator() { return coerceListToComplexValues().spliterator(); } @Override default boolean removeIf( Predicate filter ) { List cList = coerceListToComplexValues(); boolean result = cList.removeIf( filter ); if( result ) { List bList = toBindings( cList ); getList().clear(); getList().addAll( bList ); } return result; } @Override default Stream stream() { return coerceListToComplexValues().stream(); } @Override default Stream parallelStream() { return coerceListToComplexValues().parallelStream(); } @Override default void forEach( Consumer action ) { coerceListToComplexValues().forEach( action ); } @Override default int size() { return getList().size(); } @Override default boolean isEmpty() { return getList().isEmpty(); } @Override default boolean contains( Object o ) { return coerceListToComplexValues().contains( o ); } @Override default Iterator iterator() { return new Iterator() { Iterator _delegate = coerceListToComplexValues().iterator(); Iterator _actual = getList().iterator(); @Override public boolean hasNext() { return _delegate.hasNext(); } @Override public T next() { _actual.next(); return _delegate.next(); } @Override public void remove() { _actual.remove(); } }; } @Override default Object[] toArray() { return coerceListToComplexValues().toArray(); } @Override default T1[] toArray( T1[] a ) { return coerceListToComplexValues().toArray( a ); } @Override default boolean add( T t ) { return getList().add( toBindingsValue( t ) ); } default Object toBindingsValue( Object element ) { Object value = element; if( value instanceof IBindingsBacked ) { value = ((IBindingsBacked)value).getBindings(); } else if( value instanceof IListBacked ) { value = ((IListBacked)value).getList(); } else { value = RuntimeMethods.coerceToBindingValue( value ); } return value; } @Override default boolean remove( Object o ) { Object bindingValue = toBindingsValue( (T) o ); return getList().remove( bindingValue ); } @Override default boolean containsAll( Collection c ) { return coerceListToComplexValues().containsAll( c ); } @Override default boolean addAll( Collection c ) { List all = toBindings( c ); return getList().addAll( all ); } @Override default boolean addAll( int index, Collection c ) { List all = toBindings( c ); return getList().addAll( index, (Collection) all ); } default List toBindings( Collection c ) { return c.stream().map( e -> toBindingsValue( (T) e ) ).collect( Collectors.toList() ); } @Override default boolean removeAll( Collection c ) { return getList().removeAll( toBindings( c ) ); } @Override default boolean retainAll( Collection c ) { return getList().retainAll( toBindings( c ) ); } @Override default void clear() { getList().clear(); } @Override default T get( int index ) { Object o = getList().get( index ); return (T) coerce( o, getFinalComponentType() ); } @Override default T set( int index, T element ) { element = (T) toBindingsValue( element ); T result = (T) getList().set( index, element ); return result == null ? null : (T) coerce( result, getFinalComponentType() ); } @Override default void add( int index, T element ) { Object bindingValue = toBindingsValue( element ); getList().add( index, (T) bindingValue ); } @Override default T remove( int index ) { Object bindingValue = getList().remove( index ); return bindingValue == null ? null : (T) coerce( bindingValue, getFinalComponentType() ); } @Override default int indexOf( Object o ) { o = toBindingsValue( o ); return getList().indexOf( o ); } @Override default int lastIndexOf( Object o ) { o = toBindingsValue( o ); return getList().lastIndexOf( o ); } @Override default ListIterator listIterator() { return new ListIterator() { ListIterator _delegate = coerceListToComplexValues().listIterator(); ListIterator _actual = getList().listIterator(); @Override public boolean hasNext() { return _delegate.hasNext(); } @Override public T next() { _actual.next(); return _delegate.next(); } @Override public boolean hasPrevious() { return _delegate.hasPrevious(); } @Override public T previous() { _actual.previous(); return _delegate.previous(); } @Override public int nextIndex() { _actual.nextIndex(); return _delegate.nextIndex(); } @Override public int previousIndex() { _actual.previousIndex(); return _delegate.previousIndex(); } @Override public void remove() { _actual.remove(); _delegate.remove(); } @Override public void set( T t ) { _actual.set( toBindingsValue( t ) ); _delegate.set( t ); } @Override public void add( T t ) { _actual.add( toBindingsValue( t ) ); _delegate.add( t ); } }; } @Override default ListIterator listIterator( int index ) { return new ListIterator() { ListIterator _delegate = coerceListToComplexValues().listIterator( index ); ListIterator _actual = getList().listIterator( index ); @Override public boolean hasNext() { return _delegate.hasNext(); } @Override public T next() { _actual.next(); return _delegate.next(); } @Override public boolean hasPrevious() { return _delegate.hasPrevious(); } @Override public T previous() { _actual.previous(); return _delegate.previous(); } @Override public int nextIndex() { _actual.nextIndex(); return _delegate.nextIndex(); } @Override public int previousIndex() { _actual.previousIndex(); return _delegate.previousIndex(); } @Override public void remove() { _actual.remove(); _delegate.remove(); } @Override public void set( T t ) { _actual.set( toBindingsValue( t ) ); _delegate.set( t ); } @Override public void add( T t ) { _actual.add( toBindingsValue( t ) ); _delegate.add( t ); } }; } @Override default List subList( int fromIndex, int toIndex ) { return (List) getList().subList( fromIndex, toIndex ).stream() .map( e -> coerce( e, getFinalComponentType() ) ) .collect( Collectors.toList() ); } }