Package org.gocha.types

Source Code of org.gocha.types.TypesUtil$VCBinaryOpertator

/*******************************************************************************
gocha.org-lib-java Библеотека общего назначения
(с) Камнев Георгий Павлович 2009 GPLv2

Данная программа является свободным программным обеспечением. Вы вправе
распространять ее и/или модифицировать в соответствии с условиями версии 2
либо по вашему выбору с условиями более поздней версии
Стандартной Общественной Лицензии GNU, опубликованной Free Software Foundation.

Мы распространяем данную программу в надежде на то, что она будет вам полезной,
однако НЕ ПРЕДОСТАВЛЯЕМ НА НЕЕ НИКАКИХ ГАРАНТИЙ,
в том числе ГАРАНТИИ ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ
и ПРИГОДНОСТИ ДЛЯ ИСПОЛЬЗОВАНИЯ В КОНКРЕТНЫХ ЦЕЛЯХ.
Для получения более подробной информации ознакомьтесь
со Стандартной Общественной Лицензией GNU.

Вместе с данной программой вы должны были получить экземпляр
Стандартной Общественной Лицензии GNU.
Если вы его не получили, сообщите об этом в Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*******************************************************************************/

package org.gocha.types;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Stack;
import org.gocha.collection.Convertor;
import org.gocha.collection.NodesExtracter;
import org.gocha.collection.Predicate;
import org.gocha.common.Reciver;
import org.gocha.text.regex.Pattern;
import org.gocha.text.regex.Regex;

/**
* Утилита по работе с типами
* @author gocha
*/
public class TypesUtil
{
    /**
     * Предикаты по работе с типами данных JVM
     */
    public static class Predicates
    {
        /**
         * Возвращает предикат проверки метода без параметров
         * @return Предикат
         */
        public static Predicate<Method> hasEmptyParameters()
        {
            return hasParameters(emptyParametersArray);
        }

        /**
         * Возвращает предикат строгой проверкти типов аргументов метода
         * @param params Типы аргметов метода
         * @return Предикат
         */
        public static Predicate<Method> hasParameters(Class ... params)
        {
            if (params == null) {
                throw new IllegalArgumentException("params == null");
            }
            final Class[] _p = params;
            return new Predicate<Method>() {
                @Override
                public boolean validate(Method value) {
                    Class[] p = value.getParameterTypes();
                    if( p.length!=_p.length )return false;
                    for( int i=0; i<p.length; i++ )
                    {
                        if( !p[i].equals(_p[i]) )return false;
                    }
                    return true;
                }
            };
        }

        /**
         * Предикат стравения <i>value</i> <b>instanceOf</b> <i>target</i>
         * @param target Класс
         * @return Предикат
         */
        public static Predicate<Class> classInstanceOf(Class target)
        {
            final Class fTarget = target;
            return new Predicate<Class>() {
                @Override
                public boolean validate(Class value) {
                    if( fTarget==null )return value==null;
                    if( value==null )return false;
                    return AinstanceOfB(value,fTarget);
                }
            };
        }

        /**
         * Предикат сравнения <i>value</i> <b>equals</b> ( <i>target</i> )
         * @param target
         * @return Предикат
         */
        public static Predicate<Class> classEquals(Class target)
        {
            final Class fTarget = target;
            return new Predicate<Class>() {
                @Override
                public boolean validate(Class value) {
                    if( fTarget==null )return value==null;
                    return value==null ? false : fTarget.equals(value);
                }
            };
        }

        /**
         * Предикат - возвращает true, если метода возвращает указанный тип
         * @param type Возвращаемый тип
         * @return Предикат
         */
        public static Predicate<Method> returns(Class type)
        {
            if (type == null) {
                throw new IllegalArgumentException("type == null");
            }
            final Class tip = type;
            return new Predicate<Method>()
            {
                @Override
                public boolean validate(Method value)
                {
                    Class ret = value.getReturnType();
    //                return ret.equals(tip);
                    return AinstanceOfB(ret, tip);
                }
            };
        }

        /**
         * Предикат - возвращает true, если название метода начинается с указанного текста
         * @param text Текст
         * @return Предикат
         */
        public static Predicate<Method> nameStart(String text)
        {
            if (text == null) {
                throw new IllegalArgumentException("text == null");
            }
            final String txt = text;
            return new Predicate<Method>() {
                @Override
                public boolean validate(Method value) {
                    return value.getName().startsWith(txt);
                }
            };
        }

        /**
         * Предикат , возвращает true если метод имеет указаную аннатацию
         * @param annClass Аннатация
         * @return Предикат
         */
        public static Predicate<Method> hasAnnotation(Class annClass)
        {
            if (annClass == null) {
                throw new IllegalArgumentException("annClass == null");
            }

            final Class ann = annClass;

            return new Predicate<Method>() {
                @Override
                public boolean validate(Method value)
                {
                    Object a = value.getAnnotation(ann);
                    return a!=null;
                }
            };
        }

        /**
         * Предикат: Сверяет на возможность вызова метода с указанными аргументами
         * @param args Параметры
         * @return Предикат
         */
        public static Predicate<Method> callableArguments(Object[] args)
        {
            if (args == null) {
                throw new IllegalArgumentException("args == null");
            }
            final Object[] fa = args;

            return new Predicate<Method>() {
                @Override
                public boolean validate(Method value)
                {
                    Class[] types = value.getParameterTypes();
                    return isCallableArguments(types, fa);
                }
            };
        }
    }

    /**
     * Предикаты по работе с типами данных JVM
     */
    public static final Predicates predicates = new Predicates();

    /**
     * Итераторы по работе с типами данных JVM
     */
    public static class Iterators
    {
        /**
         * Возвращает параметры/агруметы метода
         * @param method Метод
         * @return Пераметры
         */
        public static Iterable<Class> paramtersOf(Method method){
            if (method == null) {
                throw new IllegalArgumentException("method == null");
            }
            Class[] params = method.getParameterTypes();
            return org.gocha.collection.Iterators.<Class>array(params);
        }

        /**
         * Возвращает публичные методы объекта
         * @param src объект
         * @param predicate Условие отбора
         * @return Перечисление методов
         */
        public static Iterable<Method> methodsOf(Object src,Predicate<Method> predicate)
        {
            if (src == null) {
                throw new IllegalArgumentException("src == null");
            }
            if (predicate == null) {
                throw new IllegalArgumentException("predicate == null");
            }
            Class c = src.getClass();
            return org.gocha.collection.Iterators.<Method>predicate(
                    org.gocha.collection.Iterators.<Method>array(c.getMethods()), predicate);
        }

        /**
         * Возвращает публичные методы объекта
         * @param obj объект
         * @return Перечисление методов
         */
        public static Iterable<Method> methodsOf( Object obj )
        {
            if (obj == null) {
                throw new IllegalArgumentException("obj == null");
            }
            return org.gocha.collection.Iterators.<Method>array(obj.getClass().getMethods());
        }

        /**
         * Возвращает публичные методы класса
         * @param cls Класс
         * @return Перечисление методов
         */
        public static Iterable<Method> methodsOf( Class cls )
        {
            if (cls == null) {
                throw new IllegalArgumentException("cls == null");
            }
            return org.gocha.collection.Iterators.<Method>array(cls.getMethods());
        }

        /**
         * Возвращает публичные поля класса
         * @param cls Класс
         * @return Перечисление полей
         */
        public static Iterable<Field> fieldsOf( Class cls )
        {
            if (cls == null) {
                throw new IllegalArgumentException("cls == null");
            }
            return org.gocha.collection.Iterators.<Field>array(cls.getFields());
        }

        /**
         * Возвращает объевленные методы только в этом классе данного объекта
         * @param obj Объект
         * @return Перечисление методов
         */
        public static Iterable<Method> declaredMethodsOf( Object obj )
        {
            if (obj == null) {
                throw new IllegalArgumentException("obj == null");
            }
            return org.gocha.collection.Iterators.<Method>array(obj.getClass().getDeclaredMethods());
        }

        /**
         * Возвращает публичные свойства объекта
         * @param object Объект
         * @return Свойства
         */
        public static Iterable<ValueController> propertiesOf(Object object)
        {
            if (object == null) {
                throw new IllegalArgumentException("object == null");
            }

            return PropertyController.buildControllers(object);
        }

        /**
         * Возвращает публичные свойства объекта
         * @param cls класс
         * @return Свойства
         */
        public static Iterable<? extends ValueController> propertiesOfClass(Class cls)
        {
            if (cls == null) {
                throw new IllegalArgumentException("object == null");
            }

            return PropertyController.buildPropertiesList(cls);
        }
    }

    /**
     * Итераторы по работе с типами данных JVM
     */
    public static final Iterators iterators = new Iterators();

    /**
     * Выполняет конструкция A <b>instanceOf</b> B
     * @param cA Класс A
     * @param cB Класс B
     * @return true - удалетворяет конструкции, false - не удавлетворяет
     */
    public static boolean AinstanceOfB(Class cA, Class cB)
    {
        if (cA == null) {
            throw new IllegalArgumentException("cA == null");
        }
        if (cB == null) {
            throw new IllegalArgumentException("cB == null");
        }
        return cB.isAssignableFrom(cA);
    }

    /**
     * Сверяет на возможность вызова метода с указанными аргументами
     * @param types Типы принимаемых параметорв
     * @param args Параметры
     * @return true - вызвать возможно, false - не возможно вызвать
     */
    public static boolean isCallableArguments(Class[] types,Object[] args)
    {
        if (types == null) {
            throw new IllegalArgumentException("types == null");
        }
        if (args == null) {
            throw new IllegalArgumentException("args == null");
        }

        if (types.length != args.length) {
            return false;
        }

        boolean callable = true;

        for (int paramIdx = 0; paramIdx < types.length; paramIdx++) {
            if (args[paramIdx] == null) {
                continue;
            }
            Class cArg = args[paramIdx].getClass();
            Class cMethodPrm = types[paramIdx];

            boolean assign = cMethodPrm.isAssignableFrom(cArg);
            if (!assign)
            {
                callable = false;
                break;
            }
        }

        return callable;
    }

    /**
     * Копирует значения из текстовой карты
     * @param map Текстовая карта (откуда копировать)
     * @param valueControllers Значения (куда копировать)
     * @return  Кол-во скопированных значений
     */
    public static int textMapToValueControllers(
            Map map,
            Iterable<ValueController> valueControllers)
    {
        return textMapToValueControllers(map, valueControllers, null, null);
    }

    /**
     * Копирует значения в текстовую карту
     * @param valueControllers Значения
     * @param map Текстовая карта
     * @return  Кол-во скопированных значений
     */
    public static int valueControllersToTextMap(
            Iterable<ValueController> valueControllers,
            Map map)
    {
        return valueControllersToTextMap(valueControllers, map, null, null);
    }

    /**
     * Копирует текстовую карту (значения) в карту значений (свойств/полей)
     * @param map Исходная карта - (текстовая)
     * @param valueControllers Конечная карта - (значения)
     * @param convertors Конвертор типов (текст/значение; может быть null)
     * @param mapKeyConvertor Конвертор ключей текстовой карты (может быть null)
     * @param valueNameConvertor Конвертор имен свойств (может быть null)
     * @param errorReciver Прием сообщений ошибок (может быть null)
     * @return Кол-во скопированных значений
     */
    public static int textMapToValueControllers(
            Map map,
            Iterable<ValueController> valueControllers,
            TypesConverters convertors,
            Convertor<String,String> mapKeyConvertor,
            Convertor<String,String> valueNameConvertor,
            Reciver<Throwable> errorReciver)
    {
        if (valueControllers == null) {
            throw new IllegalArgumentException("valueControllers == null");
        }
        if (map == null) {
            throw new IllegalArgumentException("map == null");
        }
        if( convertors==null )convertors = DefaultTypesConvertors.instance();

        int res = 0;
        for( ValueController vc : valueControllers )
        {
            String vcName = vc.getName();
            if( valueNameConvertor!=null )vcName = valueNameConvertor.convert(vcName);
            if( vcName==null )continue;

            Class vcClass = vc.getType();

            ToValueConvertor c2v = convertors.toValueFor(vcClass);

            if( c2v==null )continue;
            try
            {
                if( mapKeyConvertor!=null ){
                    for( Object oMapKey : map.keySet() ){
                        if( oMapKey==null )continue;

                        String sMapKey = oMapKey.toString();
                        sMapKey = mapKeyConvertor.convert(sMapKey);
                        if( sMapKey==null )continue;

                        if( sMapKey.equals(vcName) ){
                            Object oval = map.get(oMapKey);
                            String sval = null;
                            if( oval!=null )sval = oval.toString();
                            if( sval!=null )
                            {
                                Object destValue = c2v.convertToValue(sval);
                                vc.setValue(destValue);
                                res++;
                            }
                        }
                    }
                }else{
                    if( map.containsKey(vcName) )
                    {
                        Object oval = map.get(vcName);
                        String sval = null;
                        if( oval!=null )sval = oval.toString();
                        if( sval!=null )
                        {
                            Object destValue = c2v.convertToValue(sval);
                            vc.setValue(destValue);
                            res++;
                        }
                    }
                }
            }
            catch(Throwable t)
            {
                if( errorReciver!=null ){
                    errorReciver.recive(t);
                }else{
                    System.err.println(t.getMessage());
                }
            }
        }

        return res;
    }

    /**
     * Копирует текстовую карту (значения) в карту значений (свойств/полей)
     * @param map Исходная карта - (текстовая)
     * @param valueControllers Конечная карта - (значения)
     * @param convertors Конвертор типов (текст/значение; может быть null)
     * @param errorReciver Прием сообщений ошибок (может быть null)
     * @return Кол-во скопированных значений
     */
    public static int textMapToValueControllers(
            Map map,
            Iterable<ValueController> valueControllers,
            TypesConverters convertors,
            Reciver<Throwable> errorReciver)
    {
        return textMapToValueControllers(map, valueControllers, convertors, null, null, errorReciver);
    }

    /**
     * Копирует карту значений в текстовую карту
     * @param valueControllers Исходная карта значений
     * @param map Конечная текстовая карта
     * @param convertors Конвертор типов (текст/значение; может быть null)
     * @param mapKeyConvertor Конвертор ключей текстовой карты (может быть null)
     * @param valueNameConvertor Конвертор имен свойств (может быть null)
     * @param errorReciver Прием сообщений ошибок (может быть null)
     * @return Кол-во скопированных значений
     */
    public static int valueControllersToTextMap(
            Iterable<ValueController> valueControllers,
            Map map,
            TypesConverters convertors,
            Convertor<String,String> mapKeyConvertor,
            Convertor<String,String> valueNameConvertor,
            Reciver<Throwable> errorReciver
    ){
        if (valueControllers == null) {
            throw new IllegalArgumentException("valueControllers == null");
        }
        if (map == null) {
            throw new IllegalArgumentException("map == null");
        }
        if( convertors==null )convertors = DefaultTypesConvertors.instance();

        int count = 0;

        for( ValueController vc : valueControllers )
        {
            String vcName = vc.getName();
            if( valueNameConvertor!=null )vcName = valueNameConvertor.convert(vcName);
            if( vcName==null )continue;

            Class vcClass = vc.getType();
            ToStringConverter c2s = convertors.toStringFrom(vcClass);

            if( c2s==null )continue;
            try
            {
                Object v = vc.getValue();
                if( v==null )continue;

                String sval = c2s.convertToString(v);
                if( sval!=null )
                {
                    String key = vc.getName();
                    if( mapKeyConvertor!=null )key = mapKeyConvertor.convert(key);
                    if( key==null )continue;

                    map.put(key, sval);
                    count++;
                }
            }
            catch(Throwable t)
            {
                if( errorReciver!=null ){
                    errorReciver.recive(t);
                }else{
                    System.err.println(t.getMessage());
                }
            }
        }

        return count;
    }

    /**
     * Копирует карту значений в текстовую карту
     * @param valueControllers Исходная карта значений
     * @param map Конечная текстовая карта
     * @param convertors Конвертор типов (текст/значение; может быть null)
     * @param errorReciver Прием сообщений ошибок (может быть null)
     * @return Кол-во скопированных значений
     */
    public static int valueControllersToTextMap(
            Iterable<ValueController> valueControllers,
            Map map,
            TypesConverters convertors,
            Reciver<Throwable> errorReciver
    ){
        return valueControllersToTextMap(valueControllers, map, convertors, null, null, errorReciver);
    }

    // <editor-fold defaultstate="collapsed" desc="valueControllerExpression">
    /**
     * Создает булево выражение проверки имени свойства.
     * <p>
     * <b>Синтаксис выражения</b><br/>
     * Результат выражения - булева функция.
     * Части выражения должны обязательно разделяться пробелами.
     * <p>
     * <b>Имя свойства</b><br/>
     * Имя свойства сверяется с шаблоном (Wildcard).
     * Шаблон может содержать следующие подстановочные символы: <b>?</b> - Любой символ (один раз),
     * <b>*</b> - Любой символ от 0 и более раз (минимально возможное кол-во).
     * <br/><br/>
     * Пример: <br />
     * Задан шаблон: def*ab?<br/>
     * Ему будут соответствовать все свойства начинаюшиеся def и содержащие 3 последние буквы a, b и любую другую
     * </p>
     * @param exp Выражение
     * @return Предикат проверки или null если выражение не правильно составлено.
     */
    public static Predicate<ValueController> valueControllerExpression(String exp)
    {
        if (exp == null) {
            throw new IllegalArgumentException("exp == null");
        }

        String[] toks = exp.split("\\s+");

        Stack<Predicate<ValueController>> stack = new Stack<Predicate<ValueController>>();
        Stack<Integer> stackOp = new Stack<Integer>(); //0-or; 1-and; 2-not

        int state = 0;
        int pushPopSumm = 0;

        for (String tok : toks) {
            boolean isNot = tok.equalsIgnoreCase("not") || tok.equalsIgnoreCase("!");
            boolean isOr = tok.equalsIgnoreCase("or") || tok.equalsIgnoreCase("|");
            boolean isAnd = tok.equalsIgnoreCase("and") || tok.equalsIgnoreCase("&");
            boolean isPush = tok.equals("(");
            boolean isPop = tok.equals(")");
            boolean isMask = !(isOr || isAnd || isPush || isPop || isNot);

            if (isPush) {
                pushPopSumm++;

            }
            if (isPop) {
                pushPopSumm--;

            }
            if (pushPopSumm < 0) {
                return null;


            }
            switch (state) {
                case 0: //accpet:
                    if (isMask) {
                        stack.push(vcNameMaskPredicate(tok));
                        state = 1;
                    }
                    else if (isPush) {
                        state = 0;
                    }
                    else if (isNot) {
                        stackOp.push(2);
                        state = 2;
                    }
                    else {
                        return null;
                    }
                    break;
                case 1:
                    if (isOr || isAnd) {
                        Integer opCode = isOr ? 0 : (isAnd ? 1 : -1);
                        stackOp.push(opCode);
                        state = 2;
                    }
                    else if (isPop) {
                        if (!VCEvalOperators(stack, stackOp)) {
                            return null;

                        }
                        state = 1;
                    }
                    else {
                        return null;
                    }
                    break;
                case 2:
                    if (isMask) {
                        stack.push(vcNameMaskPredicate(tok));
                        if (!VCEvalOperators(stack, stackOp)) {
                            return null;

                        }
                        state = 1;
                    }
                    else if (isPush) {
                        state = 0;
                    }
                    else if (isNot) {
                        stackOp.push(2);
                        state = 2;
                    }
                    else {
                        return null;
                    }
                    break;
            }
        }

        if (!stack.empty() && stack.size() == 1 && stackOp.empty()) {
            return stack.pop();


        }
        return null;
    }

    private static boolean VCEvalOperators(Stack<Predicate<ValueController>> stack, Stack<Integer> stackOp)
    {
        if (stackOp.empty()) {
            return false;


        }
        int opCode = stackOp.pop();

        if (opCode == 0 || opCode == 1) {
            if (stack.size() < 2) {
                return false;


            }
            Predicate<ValueController> pb = stack.pop();
            Predicate<ValueController> pa = stack.pop();
            switch (opCode) {
                case 0:
                    stack.add(VCOROperator(pa, pb));
                    break;
                case 1:
                    stack.add(VCANDOpeartor(pa, pb));
                    break;
            }

            return true;
        }

        if (opCode == 2) {
            if (stack.size() < 1) {
                return false;


            }
            Predicate<ValueController> s = stack.pop();
            stack.add(VCNOTOperator(s));

            return true;
        }

        return false;
    }

    private static Predicate<ValueController> VCNOTOperator(Predicate<ValueController> sourcePredicate)
    {
        VCNotOperator n = new VCNotOperator();
        n.sourcePredicate = sourcePredicate;
        return n;
    }

    private static Predicate<ValueController> VCOROperator(Predicate<ValueController>... predicates)
    {
        VCBinaryOpertator bOp = new VCBinaryOpertator();
        bOp.vals = predicates;
        bOp.opCode = 0;
        return bOp;
    }

    private static Predicate<ValueController> VCANDOpeartor(Predicate<ValueController>... predicates)
    {
        VCBinaryOpertator bOp = new VCBinaryOpertator();
        bOp.vals = predicates;
        bOp.opCode = 1;
        return bOp;
    }

    private static class VCPropertyNameWildcardOperator implements Predicate<ValueController>
    {

        public String mask = "";

        @Override
        public boolean validate(ValueController value)
        {
            Pattern ptrn = Regex.parseWildcard(mask, true, '?', '*', '\\');
            String name = value.getName();
            return ptrn.match(name, 0).isMatched();
        }

        @Override
        public String toString()
        {
            return mask;
        }
    }

    private static class VCNotOperator implements Predicate<ValueController>
    {

        public Predicate<ValueController> sourcePredicate = null;

        @Override
        public boolean validate(ValueController value)
        {
            return !sourcePredicate.validate(value);
        }
    }

    private static Predicate<ValueController> vcNameMaskPredicate(String mask)
    {
        VCPropertyNameWildcardOperator uop = new VCPropertyNameWildcardOperator();
        uop.mask = mask;
        return uop;
    }

    private static class VCBinaryOpertator implements Predicate<ValueController>
    {

        public Predicate<ValueController>[] vals = null;
        public int opCode = -1; // 0 - OR; 1- AND

        @Override
        public boolean validate(ValueController value)
        {
            switch (opCode) {
                case 0:
                    for (Predicate<ValueController> p : vals) {
                        if (p.validate(value)) {
                            return true;

                        }

                    }
                    return false;
                case 1:
                    for (Predicate<ValueController> p : vals) {
                        if (!p.validate(value)) {
                            return false;

                        }

                    }
                    return true;
                default:
                    throw new Error("unknow op");
            }
        }

        @Override
        public String toString()
        {
            String r = "";

            switch (opCode) {
                case 0:
                    r += "or(";
                    break;
                case 1:
                    r += "and(";
                    break;
            }

            int i = -1;

            for (Object o : vals) {
                i++;
                if (i > 0) {
                    r += ",";

                }
                r += o.toString();
            }

            r += ")";
            return r;
        }
    }
    // </editor-fold>

    private static NodesExtracter classMethodsExtracter = null;

    /**
     * Возвращает интерфейс доступа к методам класса
     * @return интерфейс доступа к методам класса
     */
    public static NodesExtracter classMethodsExtracter()
    {
        if( classMethodsExtracter!=null )return classMethodsExtracter;
        classMethodsExtracter = new NodesExtracter() {
            @Override
            public Iterable extract(Object from)
            {
                if( from==null )return null;
                if( !(from instanceof Class) )return null;
                return Iterators.methodsOf((Class)from);
            }
        };
        return null;
    }

    private static NodesExtracter methodParametersExtracter = null;

    /**
     * Возвращает интерфейс доступа к типам параметров метода
     * @return интерфейс доступа к типам параметров метода
     */
    public static NodesExtracter methodParametersExtracter()
    {
        if( methodParametersExtracter!=null )return methodParametersExtracter;
        methodParametersExtracter = new NodesExtracter() {
            @Override
            public Iterable extract(Object from)
            {
                if( from==null )return null;
                if( !(from instanceof Method) ) {
                    return null;
                }
                return Iterators.paramtersOf((Method)from);
            }
        };
        return null;
    }

    /**
     * Пустой массив: Class[]
     */
    public static final Class[] emptyParametersArray = new Class[]{};
}
TOP

Related Classes of org.gocha.types.TypesUtil$VCBinaryOpertator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.