Search in sources :

Example 6 with ActionProcessor

use of io.atlasmap.spi.ActionProcessor in project atlasmap by atlasmap.

the class DefaultAtlasFieldActionsServiceTest method testProcessActionWithActionActionDetailObjectAssignableType.

@Test
public void testProcessActionWithActionActionDetailObjectAssignableType() throws AtlasException {
    Action action = new AbsoluteValue();
    Object sourceObject = Integer.valueOf("1");
    ActionProcessor processor = fieldActionsService.findActionProcessor(action, FieldType.STRING);
    assertEquals(1L, processor.process(action, sourceObject));
}
Also used : Action(io.atlasmap.v2.Action) AbsoluteValue(io.atlasmap.v2.AbsoluteValue) ActionProcessor(io.atlasmap.spi.ActionProcessor) Test(org.junit.jupiter.api.Test)

Example 7 with ActionProcessor

use of io.atlasmap.spi.ActionProcessor in project atlasmap by atlasmap.

the class DefaultAtlasFunctionResolver method resolve.

@Override
public Expression resolve(final String name, List<Expression> args) throws ParseException {
    String functionName = name.toUpperCase();
    FunctionFactory f = functions.get(functionName);
    if (f != null) {
        return f.create(args);
    } else {
        // lookup action
        return (ctx) -> {
            List<Field> arguments = new ArrayList<>();
            for (Expression arg : args) {
                arguments.add(arg.evaluate(ctx));
            }
            Object valueForTypeEvaluation = null;
            if (arguments.isEmpty()) {
                return null;
            } else {
                valueForTypeEvaluation = arguments.get(arguments.size() - 1);
            }
            ActionProcessor actionProcessor = fieldActionService.findActionProcessor(name, valueForTypeEvaluation);
            if (actionProcessor != null) {
                Map<String, Object> actionParameters = new HashMap<>();
                ActionParameters actionDetailParameters = actionProcessor.getActionDetail().getParameters();
                if (actionDetailParameters != null && actionDetailParameters.getParameter() != null) {
                    for (ActionParameter parameter : actionDetailParameters.getParameter()) {
                        if (!arguments.isEmpty()) {
                            Object parameterValue = arguments.remove(0).getValue();
                            actionParameters.put(parameter.getName(), parameterValue);
                        } else {
                            throw new IllegalArgumentException(String.format("The transformation '%s' expects more parameters. The parameter '%s' is missing", name, parameter.getName()));
                        }
                    }
                }
                if (arguments.isEmpty()) {
                    throw new IllegalArgumentException(String.format("The transformation '%s' expects more arguments", name));
                }
                FieldGroup fields = new FieldGroup();
                fields.getField().addAll(arguments);
                return fieldActionService.buildAndProcessAction(actionProcessor, actionParameters, fields);
            } else {
                throw new IllegalArgumentException(String.format("The expression function or transformation '%s' was not found", name));
            }
        };
    }
}
Also used : ActionParameters(io.atlasmap.v2.ActionParameters) FieldGroup(io.atlasmap.v2.FieldGroup) Expression(io.atlasmap.expression.Expression) FunctionResolver(io.atlasmap.expression.FunctionResolver) HashMap(java.util.HashMap) ServiceLoader(java.util.ServiceLoader) ParseException(io.atlasmap.expression.parser.ParseException) ArrayList(java.util.ArrayList) List(java.util.List) FunctionFactory(io.atlasmap.spi.FunctionFactory) Field(io.atlasmap.v2.Field) Map(java.util.Map) ActionProcessor(io.atlasmap.spi.ActionProcessor) ActionParameter(io.atlasmap.v2.ActionParameter) FieldGroup(io.atlasmap.v2.FieldGroup) ActionParameter(io.atlasmap.v2.ActionParameter) Expression(io.atlasmap.expression.Expression) ActionParameters(io.atlasmap.v2.ActionParameters) ArrayList(java.util.ArrayList) List(java.util.List) ActionProcessor(io.atlasmap.spi.ActionProcessor) HashMap(java.util.HashMap) Map(java.util.Map) FunctionFactory(io.atlasmap.spi.FunctionFactory)

Example 8 with ActionProcessor

use of io.atlasmap.spi.ActionProcessor in project atlasmap by atlasmap.

the class DefaultAtlasFieldActionService method createDetailFromProcessor.

private ActionProcessor createDetailFromProcessor(Class<?> clazz, Method method) {
    AtlasActionProcessor annotation = method.getAnnotation(AtlasActionProcessor.class);
    if (annotation == null) {
        return null;
    }
    if (method.getParameterCount() < 1) {
        LOG.debug("Invalid @AtlasActionProcessor method.  Expected at least 1 parameter: " + method);
    }
    Class<? extends Action> actionClazz = null;
    if (Action.class.isAssignableFrom(method.getParameterTypes()[0])) {
        actionClazz = (Class<? extends Action>) method.getParameterTypes()[0];
    } else {
        LOG.debug("Invalid @AtlasActionProcessor method.  1st parameter does not subclass " + Action.class.getName() + ": " + method);
    }
    final Class<?> targetClass = method.getReturnType();
    String name = actionResolver.toId(actionClazz);
    ActionDetail det = new ActionDetail();
    det.setClassName(clazz.getName());
    det.setMethod(method.getName());
    det.setName(name);
    det.setTargetType(toFieldType(targetClass, method.getGenericReturnType()));
    if (!clazz.getPackage().getName().equals("io.atlasmap.actions")) {
        det.setCustom(true);
    }
    Type[] genericParameterTypes = method.getGenericParameterTypes();
    if (genericParameterTypes.length >= 2) {
        Class<?> sourceClass = method.getParameterTypes()[1];
        if (annotation.sourceType() != FieldType.NONE) {
            det.setSourceType(annotation.sourceType());
        } else {
            det.setSourceType(toFieldType(sourceClass, method.getGenericParameterTypes()[1]));
        }
        CollectionType sourceCollection = toFieldCollectionType(sourceClass);
        CollectionType targetCollection = toFieldCollectionType(targetClass);
        if (sourceCollection != CollectionType.NONE) {
            if (targetCollection != CollectionType.NONE) {
                det.setMultiplicity(Multiplicity.MANY_TO_MANY);
            } else {
                det.setMultiplicity(Multiplicity.MANY_TO_ONE);
            }
        } else if (targetCollection != CollectionType.NONE) {
            det.setMultiplicity(Multiplicity.ONE_TO_MANY);
        } else {
            det.setMultiplicity(Multiplicity.ONE_TO_ONE);
        }
    } else if (genericParameterTypes.length == 1) {
        det.setMultiplicity(Multiplicity.ZERO_TO_ONE);
    }
    try {
        det.setActionSchema(actionClazz);
    } catch (Exception e) {
        LOG.error(String.format("Could not get json schema for action=%s msg=%s", clazz.getName(), e.getMessage()), e);
    }
    try {
        det.setParameters(detectFieldActionParameters(actionClazz));
    } catch (ClassNotFoundException e) {
        LOG.error(String.format("Error detecting parameters for field action=%s msg=%s", det.getName(), e.getMessage()), e);
    }
    Object o = null;
    try {
        o = Modifier.isStatic(method.getModifiers()) ? clazz.getDeclaredConstructor().newInstance() : null;
    } catch (Throwable e) {
        LOG.error(String.format("Error creating object instance for action=%s msg=%s", det.getName(), e.getMessage()), e);
    }
    final Object object = o;
    Class<? extends Action> finalActionClazz = actionClazz;
    return new ActionProcessor() {

        @Override
        public ActionDetail getActionDetail() {
            return det;
        }

        @Override
        public Class<? extends Action> getActionClass() {
            return finalActionClazz;
        }

        @Override
        public Object process(Action action, Object sourceObject) throws AtlasException {
            try {
                if (det.getMultiplicity() == Multiplicity.ZERO_TO_ONE) {
                    return method.invoke(object, action);
                } else {
                    sourceObject = convertSourceObject(sourceObject);
                    return method.invoke(object, action, sourceObject);
                }
            } catch (Throwable e) {
                throw new AtlasException(String.format("Error processing action %s", det.getName()), e);
            }
        }

        private Object convertSourceObject(Object sourceObject) throws AtlasConversionException {
            if (sourceObject == null) {
                return null;
            }
            Class<?> paramType;
            paramType = method.getParameterTypes()[1];
            CollectionType paramCollectionType = toFieldCollectionType(paramType);
            CollectionType sourceCollectionType = toFieldCollectionType(sourceObject.getClass());
            if (paramCollectionType != CollectionType.NONE) {
                List<Object> sourceList;
                Type itemType = method.getGenericParameterTypes()[1];
                Class<?> itemClass = paramType.isArray() ? paramType.getComponentType() : (Class<?>) ((ParameterizedType) itemType).getActualTypeArguments()[0];
                if (sourceCollectionType != CollectionType.NONE) {
                    if (sourceCollectionType == CollectionType.ARRAY) {
                        sourceList = Arrays.asList(sourceObject);
                    } else if (sourceCollectionType == CollectionType.LIST) {
                        sourceList = (List<Object>) sourceObject;
                    } else if (sourceCollectionType == CollectionType.MAP) {
                        sourceList = new ArrayList(((Map) sourceObject).values());
                    } else {
                        sourceList = new ArrayList((Collection) sourceObject);
                    }
                } else {
                    sourceList = Arrays.asList(sourceObject);
                }
                convertItems(sourceList, itemClass);
                if (paramType.isArray()) {
                    return sourceList.toArray();
                } else {
                    return sourceList;
                }
            } else if (paramType.isInstance(sourceObject)) {
                return sourceObject;
            }
            return conversionService.convertType(sourceObject, null, paramType, null);
        }
    };
}
Also used : CustomAction(io.atlasmap.v2.CustomAction) AtlasFieldAction(io.atlasmap.spi.AtlasFieldAction) Action(io.atlasmap.v2.Action) ActionDetail(io.atlasmap.v2.ActionDetail) ArrayList(java.util.ArrayList) AtlasActionProcessor(io.atlasmap.spi.AtlasActionProcessor) AtlasException(io.atlasmap.api.AtlasException) AtlasConversionException(io.atlasmap.api.AtlasConversionException) AtlasException(io.atlasmap.api.AtlasException) FieldType(io.atlasmap.v2.FieldType) CollectionType(io.atlasmap.v2.CollectionType) ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) CollectionType(io.atlasmap.v2.CollectionType) Collection(java.util.Collection) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) ActionProcessor(io.atlasmap.spi.ActionProcessor) AtlasActionProcessor(io.atlasmap.spi.AtlasActionProcessor) Map(java.util.Map)

Example 9 with ActionProcessor

use of io.atlasmap.spi.ActionProcessor in project atlasmap by atlasmap.

the class DefaultAtlasFieldActionService method createDetailFromFieldActionInfo.

private ActionProcessor createDetailFromFieldActionInfo(final Class<?> clazz, final Method method) {
    AtlasFieldActionInfo annotation = method.getAnnotation(AtlasFieldActionInfo.class);
    if (annotation == null) {
        return null;
    }
    final ActionDetail det = new ActionDetail();
    det.setClassName(clazz.getName());
    det.setMethod(method.getName());
    det.setName(annotation.name());
    det.setSourceType(annotation.sourceType());
    det.setTargetType(annotation.targetType());
    CollectionType sourceCollection = annotation.sourceCollectionType();
    CollectionType targetCollection = annotation.sourceCollectionType();
    if (sourceCollection != null && sourceCollection != CollectionType.NONE) {
        det.setMultiplicity(Multiplicity.MANY_TO_ONE);
    } else if (targetCollection != null && targetCollection != CollectionType.NONE) {
        det.setMultiplicity(Multiplicity.ONE_TO_MANY);
    } else {
        det.setMultiplicity(Multiplicity.ONE_TO_ONE);
    }
    Class<? extends Action> actionClazz;
    try {
        actionClazz = (Class<? extends Action>) Class.forName("io.atlasmap.v2." + annotation.name());
    } catch (Exception e) {
        actionClazz = null;
        det.setCustom(true);
    }
    try {
        det.setActionSchema(actionClazz);
    } catch (Exception e) {
        LOG.error(String.format("Could not get json schema for action=%s msg=%s", annotation.name(), e.getMessage()), e);
    }
    try {
        // TODO https://github.com/atlasmap/atlasmap/issues/538
        if (det.isCustom() == null || !det.isCustom()) {
            det.setParameters(detectFieldActionParameters(actionClazz));
        }
    } catch (ClassNotFoundException e) {
        LOG.error(String.format("Error detecting parameters for field action=%s msg=%s", annotation.name(), e.getMessage()), e);
    }
    if (LOG.isTraceEnabled()) {
        LOG.trace("Loaded FieldAction: " + det.getName());
    }
    Class<? extends Action> finalActionClazz = actionClazz;
    return new ActionProcessor() {

        @Override
        public ActionDetail getActionDetail() {
            return det;
        }

        @Override
        public Class<? extends Action> getActionClass() {
            return finalActionClazz;
        }

        @Override
        public Object process(Action action, Object sourceObject) throws AtlasException {
            Object targetObject = null;
            try {
                Object convertedSourceObject = convertSourceObject(sourceObject);
                if (Modifier.isStatic(method.getModifiers())) {
                    // cf. https://github.com/atlasmap/atlasmap/issues/536
                    if (det.isCustom() != null && det.isCustom()) {
                        targetObject = det.getMultiplicity() == Multiplicity.ZERO_TO_ONE ? method.invoke(null) : method.invoke(null, convertedSourceObject);
                    } else {
                        targetObject = det.getMultiplicity() == Multiplicity.ZERO_TO_ONE ? method.invoke(null, action) : method.invoke(null, action, convertedSourceObject);
                    }
                } else {
                    Object object = clazz.getDeclaredConstructor().newInstance();
                    if (det.isCustom() != null && det.isCustom()) {
                        targetObject = det.getMultiplicity() == Multiplicity.ZERO_TO_ONE ? method.invoke(object) : method.invoke(object, convertedSourceObject);
                    } else {
                        targetObject = det.getMultiplicity() == Multiplicity.ZERO_TO_ONE ? method.invoke(object, action) : method.invoke(object, action, convertedSourceObject);
                    }
                }
            } catch (Throwable e) {
                throw new AtlasException(String.format("Error processing action %s", det.getName()), e);
            }
            return targetObject;
        }

        private Object convertSourceObject(Object sourceObject) throws AtlasConversionException {
            Class<?> paramType;
            int paramCount = method.getParameterCount();
            if (paramCount < 2) {
                return null;
            }
            paramType = method.getParameterTypes()[1];
            if (paramType.isInstance(sourceObject)) {
                return sourceObject;
            }
            return conversionService.convertType(sourceObject, null, paramType, null);
        }
    };
}
Also used : CustomAction(io.atlasmap.v2.CustomAction) AtlasFieldAction(io.atlasmap.spi.AtlasFieldAction) Action(io.atlasmap.v2.Action) ActionDetail(io.atlasmap.v2.ActionDetail) AtlasFieldActionInfo(io.atlasmap.spi.AtlasFieldActionInfo) AtlasException(io.atlasmap.api.AtlasException) AtlasConversionException(io.atlasmap.api.AtlasConversionException) AtlasException(io.atlasmap.api.AtlasException) CollectionType(io.atlasmap.v2.CollectionType) ActionProcessor(io.atlasmap.spi.ActionProcessor) AtlasActionProcessor(io.atlasmap.spi.AtlasActionProcessor)

Example 10 with ActionProcessor

use of io.atlasmap.spi.ActionProcessor in project atlasmap by atlasmap.

the class DefaultAtlasFieldActionService method findActionProcessor.

@Override
public ActionProcessor findActionProcessor(Action action, FieldType sourceType) throws AtlasException {
    CustomAction customAction = null;
    if (action instanceof CustomAction) {
        customAction = (CustomAction) action;
        if (customAction.getClassName() == null || customAction.getMethodName() == null) {
            throw new AtlasException("The class name and method name must be specified for custom FieldAction: " + customAction.getName());
        }
    }
    List<ActionProcessor> matches = new ArrayList<>();
    Lock readLock = actionProcessorsLock.readLock();
    try {
        readLock.lock();
        for (ActionProcessor processor : actionProcessors) {
            if (customAction != null) {
                ActionDetail detail = processor.getActionDetail();
                if (customAction.getClassName().equals(detail.getClassName()) && customAction.getMethodName().equals(detail.getMethod())) {
                    matches.add(processor);
                    break;
                }
            } else if (processor.getActionClass() == action.getClass()) {
                matches.add(processor);
            }
        }
    } finally {
        readLock.unlock();
    }
    return findBestActionProcessor(matches, sourceType);
}
Also used : ActionDetail(io.atlasmap.v2.ActionDetail) CustomAction(io.atlasmap.v2.CustomAction) ArrayList(java.util.ArrayList) AtlasException(io.atlasmap.api.AtlasException) ActionProcessor(io.atlasmap.spi.ActionProcessor) AtlasActionProcessor(io.atlasmap.spi.AtlasActionProcessor) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) ReadWriteLock(java.util.concurrent.locks.ReadWriteLock) Lock(java.util.concurrent.locks.Lock)

Aggregations

ActionProcessor (io.atlasmap.spi.ActionProcessor)10 AtlasActionProcessor (io.atlasmap.spi.AtlasActionProcessor)6 Action (io.atlasmap.v2.Action)5 ActionDetail (io.atlasmap.v2.ActionDetail)4 CustomAction (io.atlasmap.v2.CustomAction)4 ArrayList (java.util.ArrayList)4 AtlasException (io.atlasmap.api.AtlasException)3 AtlasFieldAction (io.atlasmap.spi.AtlasFieldAction)3 FieldType (io.atlasmap.v2.FieldType)3 AtlasConversionException (io.atlasmap.api.AtlasConversionException)2 CollectionType (io.atlasmap.v2.CollectionType)2 Field (io.atlasmap.v2.Field)2 List (java.util.List)2 Map (java.util.Map)2 Lock (java.util.concurrent.locks.Lock)2 ReadWriteLock (java.util.concurrent.locks.ReadWriteLock)2 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)2 Test (org.junit.jupiter.api.Test)2 Expression (io.atlasmap.expression.Expression)1 FunctionResolver (io.atlasmap.expression.FunctionResolver)1