package ru.vyarus.guice.persist.orient.repository.command.ext.ridelvar; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.orientechnologies.orient.core.command.OCommandRequest; import com.orientechnologies.orient.core.record.impl.ODocument; import ru.vyarus.guice.persist.orient.db.util.RidUtils; import ru.vyarus.guice.persist.orient.repository.command.core.param.CommandParamsContext; import ru.vyarus.guice.persist.orient.repository.command.core.spi.CommandExtension; import ru.vyarus.guice.persist.orient.repository.command.core.spi.CommandMethodDescriptor; import ru.vyarus.guice.persist.orient.repository.command.core.spi.SqlCommandDescriptor; import ru.vyarus.guice.persist.orient.repository.core.MethodExecutionException; import ru.vyarus.guice.persist.orient.repository.core.spi.parameter.MethodParamExtension; import ru.vyarus.guice.persist.orient.repository.core.spi.parameter.ParamInfo; import javax.inject.Singleton; import java.lang.reflect.Array; import java.util.Iterator; import java.util.List; import java.util.Map; import static ru.vyarus.guice.persist.orient.repository.core.MethodDefinitionException.check; import static ru.vyarus.guice.persist.orient.repository.core.MethodExecutionException.checkExec; /** * {@link RidElVar} param extension. * * @author Vyacheslav Rusakov * @since 02.06.2015 */ @Singleton public class RidElVarParamExtension implements CommandExtension<CommandMethodDescriptor>, MethodParamExtension<CommandMethodDescriptor, CommandParamsContext, RidElVar> { public static final String KEY = RidElVarParamExtension.class.getName(); @Override public void processParameters(final CommandMethodDescriptor descriptor, final CommandParamsContext context, final List<ParamInfo<RidElVar>> paramsInfo) { final Map<String, Integer> varsMapping = Maps.newHashMap(); for (ParamInfo<RidElVar> param : paramsInfo) { final String name = Strings.emptyToNull(param.annotation.value()); check(name != null, "Rid variable name required"); // duplicate check context.addDynamicElVarValue(name); varsMapping.put(name, param.position); } descriptor.extDescriptors.put(KEY, varsMapping); } @Override public void amendCommandDescriptor(final SqlCommandDescriptor sql, final CommandMethodDescriptor descriptor, final Object instance, final Object... arguments) { @SuppressWarnings("unchecked") final Map<String, Integer> vars = (Map<String, Integer>) descriptor.extDescriptors.get(KEY); for (Map.Entry<String, Integer> entry : vars.entrySet()) { final String key = entry.getKey(); final Object value = arguments[entry.getValue()]; try { sql.elVars.put(key, convert(value)); } catch (Exception e) { throw new MethodExecutionException(String.format("Invalid rid el variable '%s'", key), e); } } } @Override public void amendCommand(final OCommandRequest query, final CommandMethodDescriptor descriptor, final Object instance, final Object... arguments) { // not used } private String convert(final Object value) { checkExec(value != null, "Not null value required"); final String res; if (value instanceof ODocument) { // ODocument is iterable, so need to check it first res = RidUtils.getRid(value); } else if (value instanceof Iterable) { res = convertCollection(((Iterable) value).iterator()); } else if (value instanceof Iterator) { res = convertCollection((Iterator) value); } else if (value.getClass().isArray()) { res = convertArray(value); } else { res = RidUtils.getRid(value); } return res; } private String convertArray(final Object array) { final List<Object> res = Lists.newArrayList(); for (int i = 0; i < Array.getLength(array); i++) { res.add(Array.get(array, i)); } return convertCollection(res.iterator()); } private String convertCollection(final Iterator iterator) { final StringBuilder builder = new StringBuilder("["); while (iterator.hasNext()) { builder.append(RidUtils.getRid(iterator.next())); if (iterator.hasNext()) { builder.append(','); } } builder.append(']'); return builder.toString(); } }