app/src/main/java/db/juhaku/juhakudb/repository/RepositoryFactory.java
/**
     * Create proxy implementation of repository for given interface. This is the default scenario
     * when there is no custom implementation class provided. {@link SimpleAndroidRepository} will
     * be proxied to the interface of the repository.
     *
     * @param interf Class instance of repository interface.
     * @param simpleAndroidRepository Instance of {@link SimpleAndroidRepository} to provide proxy for.
     * @return Proxied repository for given interface class.
     *
     * @since 1.3.0
     *
     * @hide
     */
Create proxy implementation of repository for given interface. This is the default scenario
when there is no custom implementation class provided.  SimpleAndroidRepository will
be proxied to the interface of the repository.

@param interf Class instance of repository interface.
@param simpleAndroidRepository Instance of  SimpleAndroidRepository to provide proxy for.
@return Proxied repository for given interface class.



@hide
Create proxy implementation of repository for given interface . This is the default scenario when there is no custom implementation class provided . SimpleAndroidRepository will be proxied to the interface of the repository . @param interf Class instance of repository interface . @param simpleAndroidRepository Instance of SimpleAndroidRepository to provide proxy for . @return Proxied repository for given interface class . @hide
private static <T> T proxyImpl(final Class<T> interf, final SimpleAndroidRepository simpleAndroidRepository) {
        return (T) Proxy.newProxyInstance(interf.getClassLoader(), new Class[]{interf}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Method repositoryMethod = findMethodWithSameErasure(method);
                if (repositoryMethod == null) {
                    Log.w(getClass().getName(), "Could not find method: " + method.getName() + " with params: "
                            + method.getParameterTypes() + " with return type: " + method.getReturnType() + " from repository: " + interf);
                    throw new NoSuchMethodException("Method with same erasure not found, cannot execute method: " + method.getName());
                }
                Log.v(getClass().getName(), "Executing method: " + method.getName() + " with args: "
                        + (args != null ? StringUtils.arrayToString(args) : null) + " in: " + interf);
                return repositoryMethod.invoke(simpleAndroidRepository, args);
            }
            /**
             * Find method with same erasure as is being executed in proxy interface. Method is
             * checked by name, return type and parameter types and order or parameter types.
             *
             * @param method Method to look for.
             * @return Found method or null.
             *
             * @since 1.3.0
             *
             * @hide
             */
            private Method findMethodWithSameErasure(Method method) {
                for (Method m : simpleAndroidRepository.getClass().getMethods()) {
                    boolean accessible = m.isAccessible();
                    m.setAccessible(true);
                    if (m.getName().equals(method.getName()) && m.getReturnType().equals(method.getReturnType())) {
                        boolean hasParams = true;
                        for (int i = 0; i < m.getParameterTypes().length; i++) {
                            if (m.getParameterTypes()[i].equals(method.getParameterTypes()[i])) {
                                continue;
                            }
                            hasParams = false;
                            break;
                        }
                        if (hasParams) {
                            return m;
                        }
                    }
                    m.setAccessible(accessible);
                }
                return null;
            }
        });
    }
private static < T > T proxyImpl ( final Class < T > interf , final SimpleAndroidRepository simpleAndroidRepository ) { return ( T ) Proxy . newProxyInstance ( interf . getClassLoader ( ) , new Class [ ] { interf } , new InvocationHandler ( ) { @ Override public Object invoke ( Object proxy , Method method , Object [ ] args ) throws Throwable { Method repositoryMethod = findMethodWithSameErasure ( method ) ; if ( repositoryMethod == null ) { Log . w ( getClass ( ) . getName ( ) , "Could not find method: " + method . getName ( ) + " with params: " + method . getParameterTypes ( ) + " with return type: " + method . getReturnType ( ) + " from repository: " + interf ) ; throw new NoSuchMethodException ( "Method with same erasure not found, cannot execute method: " + method . getName ( ) ) ; } Log . v ( getClass ( ) . getName ( ) , "Executing method: " + method . getName ( ) + " with args: " + ( args != null ? StringUtils . arrayToString ( args ) : null ) + " in: " + interf ) ; return repositoryMethod . invoke ( simpleAndroidRepository , args ) ; } /**
             * Find method with same erasure as is being executed in proxy interface. Method is
             * checked by name, return type and parameter types and order or parameter types.
             *
             * @param method Method to look for.
             * @return Found method or null.
             *
             * @since 1.3.0
             *
             * @hide
             */ private Method findMethodWithSameErasure ( Method method ) { for ( Method m : simpleAndroidRepository . getClass ( ) . getMethods ( ) ) { boolean accessible = m . isAccessible ( ) ; m . setAccessible ( true ) ; if ( m . getName ( ) . equals ( method . getName ( ) ) && m . getReturnType ( ) . equals ( method . getReturnType ( ) ) ) { boolean hasParams = true ; for ( int i = 0 ; i < m . getParameterTypes ( ) . length ; i ++ ) { if ( m . getParameterTypes ( ) [ i ] . equals ( method . getParameterTypes ( ) [ i ] ) ) { continue ; } hasParams = false ; break ; } if ( hasParams ) { return m ; } } m . setAccessible ( accessible ) ; } return null ; } } ) ; }
Create proxy implementation of repository for given interface.
Create proxy implementation of repository for given interface .
// Add some trace logging if enabled. // Set method accessible. // Check that we have right method by name and return type. // Check that method has same amount of parameters with same classes. // If all the parameters are same execution can be processed. // Restore default accessible status.