text:
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.source.resolve.reference.impl;

import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.PrioritizedLookupElement;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.*;
import java.util.function.Function;

/**
 * @author Pavel.Dolgov
 */
public class JavaReflectionReferenceUtil {
  // MethodHandle (Java 7) and VarHandle (Java 9) infrastructure
  public static final String JAVA_LANG_INVOKE_METHOD_HANDLES_LOOKUP = "java.lang.invoke.MethodHandles.Lookup";
  public static final String JAVA_LANG_INVOKE_METHOD_TYPE = "java.lang.invoke.MethodType";

  public static final String METHOD_TYPE = "methodType";
  public static final String GENERIC_METHOD_TYPE = "genericMethodType";

  public static final String FIND_VIRTUAL = "findVirtual";
  public static final String FIND_STATIC = "findStatic";
  public static final String FIND_SPECIAL = "findSpecial";

  public static final String FIND_GETTER = "findGetter";
  public static final String FIND_SETTER = "findSetter";
  public static final String FIND_STATIC_GETTER = "findStaticGetter";
  public static final String FIND_STATIC_SETTER = "findStaticSetter";

  public static final String FIND_VAR_HANDLE = "findVarHandle";
  public static final String FIND_STATIC_VAR_HANDLE = "findStaticVarHandle";

  public static final String FIND_CONSTRUCTOR = "findConstructor";
  public static final String FIND_CLASS = "findClass";

  public static final String[] HANDLE_FACTORY_METHOD_NAMES = {
    FIND_VIRTUAL, FIND_STATIC, FIND_SPECIAL,
    FIND_GETTER, FIND_SETTER,
    FIND_STATIC_GETTER, FIND_STATIC_SETTER,
    FIND_VAR_HANDLE, FIND_STATIC_VAR_HANDLE};

  // Classic reflection infrastructure
  public static final String GET_FIELD = "getField";
  public static final String GET_DECLARED_FIELD = "getDeclaredField";
  public static final String GET_METHOD = "getMethod";
  public static final String GET_DECLARED_METHOD = "getDeclaredMethod";
  public static final String GET_CONSTRUCTOR = "getConstructor";
  public static final String GET_DECLARED_CONSTRUCTOR = "getDeclaredConstructor";

  public static final String JAVA_LANG_CLASS_LOADER = "java.lang.ClassLoader";
  public static final String FOR_NAME = "forName";
  public static final String LOAD_CLASS = "loadClass";
  public static final String GET_CLASS = "getClass";
  public static final String NEW_INSTANCE = "newInstance";
  public static final String TYPE = "TYPE";

  // Atomic field updaters
  public static final String NEW_UPDATER = "newUpdater";
  public static final String ATOMIC_LONG_FIELD_UPDATER = "java.util.concurrent.atomic.AtomicLongFieldUpdater";
  public static final String ATOMIC_INTEGER_FIELD_UPDATER = "java.util.concurrent.atomic.AtomicIntegerFieldUpdater";
  public static final String ATOMIC_REFERENCE_FIELD_UPDATER = "java.util.concurrent.atomic.AtomicReferenceFieldUpdater";

  private static final RecursionGuard<PsiElement> ourGuard = RecursionManager.createGuard("JavaLangClassMemberReference");

  @Contract("null -> null")
  public static ReflectiveType getReflectiveType(@Nullable PsiExpression context) {
    context = ParenthesesUtils.stripParentheses(context);
    if (context == null) {
      return null;
    }
    if (context instanceof PsiClassObjectAccessExpression) {
      final PsiTypeElement operand = ((PsiClassObjectAccessExpression)context).getOperand();
      return ReflectiveType.create(operand.getType(), true);
    }

    if (context instanceof PsiMethodCallExpression) {
      final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)context;
      final String methodReferenceName = methodCall.getMethodExpression().getReferenceName();
      if (FOR_NAME.equals(methodReferenceName)) {
        final PsiMethod method = methodCall.resolveMethod();
        if (method != null && isJavaLangClass(method.getContainingClass())) {
          final PsiExpression[] expressions = methodCall.getArgumentList().getExpressions();
          if (expressions.length == 1) {
            final PsiExpression argument = findDefinition(ParenthesesUtils.stripParentheses(expressions[0]));
            final String className = computeConstantExpression(argument, String.class);
            if (className != null) {
              return ReflectiveType.create(findClass(className, context), true);
            }
          }
        }
      }
      else if (GET_CLASS.equals(methodReferenceName) && methodCall.getArgumentList().isEmpty()) {
        final PsiMethod method = methodCall.resolveMethod();
        if (method != null && isJavaLangObject(method.getContainingClass())) {
          final PsiExpression qualifier = ParenthesesUtils.stripParentheses(methodCall.getMethodExpression().getQualifierExpression());
          if (qualifier instanceof PsiReferenceExpression) {
            final PsiExpression definition = findVariableDefinition((PsiReferenceExpression)qualifier);
            if (definition != null) {
              return getClassInstanceType(definition);
            }
          }
          //TODO type of the qualifier may be a supertype of the actual value - need to compute the type of the actual value
          // otherwise getDeclaredField and getDeclaredMethod may work not reliably
          if (qualifier != null) {
            return getClassInstanceType(qualifier);
          }
        }
      }
    }

    if (context instanceof PsiReferenceExpression) {
      PsiReferenceExpression reference = (PsiReferenceExpression)context;
      final PsiElement resolved = reference.resolve();
      if (resolved instanceof PsiVariable) {
        PsiVariable variable = (PsiVariable)resolved;
        if (isJavaLangClass(PsiTypesUtil.getPsiClass(variable.getType()))) {
          final PsiExpression definition = findVariableDefinition(reference, variable);
          if (definition != null) {
            ReflectiveType result = ourGuard.doPreventingRecursion(variable, false, () -> getReflectiveType(definition));
            if (result != null) {
              return result;
            }
          }
        }
      }
    }

    final PsiType type = context.getType();
    if (type instanceof PsiClassType) {
      final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
      final PsiClass resolvedElement = resolveResult.getElement();
      if (!isJavaLangClass(resolvedElement)) return null;

      if (context instanceof PsiReferenceExpression && TYPE.equals(((PsiReferenceExpression)context).getReferenceName())) {
        final PsiElement resolved = ((PsiReferenceExpression)context).resolve();
        if (resolved instanceof PsiField) {
          final PsiField field = (PsiField)resolved;
          if (field.hasModifierProperty(PsiModifier.FINAL) && field.hasModifierProperty(PsiModifier.STATIC)) {
            final PsiType[] classTypeArguments = ((PsiClassType)type).getParameters();
            final PsiPrimitiveType unboxedType = classTypeArguments.length == 1
                                                 ? PsiPrimitiveType.getUnboxedType(classTypeArguments[0]) : null;
            if (unboxedType != null && field.getContainingClass() == PsiUtil.resolveClassInClassTypeOnly(classTypeArguments[0])) {
              return ReflectiveType.create(unboxedType, true);
            }
          }
        }
      }
      final PsiTypeParameter[] parameters = resolvedElement.getTypeParameters();
      if (parameters.length == 1) {
        final PsiType typeArgument = resolveResult.getSubstitutor().substitute(parameters[0]);
        final PsiType erasure = TypeConversionUtil.erasure(typeArgument);
        final PsiClass argumentClass = PsiTypesUtil.getPsiClass(erasure);
        if (argumentClass != null && !isJavaLangObject(argumentClass)) {
          return ReflectiveType.create(argumentClass, false);
        }
      }
    }
    return null;
  }

  @Nullable
  private static ReflectiveType getClassInstanceType(@Nullable PsiExpression expression) {
    expression = ParenthesesUtils.stripParentheses(expression);
    if (expression == null) {
      return null;
    }
    if (expression instanceof PsiMethodCallExpression) {
      final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression;
      final String methodReferenceName = methodCall.getMethodExpression().getReferenceName();

      if (NEW_INSTANCE.equals(methodReferenceName)) {
        final PsiMethod method = methodCall.resolveMethod();
        if (method != null) {
          final PsiExpression[] arguments = methodCall.getArgumentList().getExpressions();
          if (arguments.length == 0 && isClassWithName(method.getContainingClass(), CommonClassNames.JAVA_LANG_CLASS)) {
            final PsiExpression qualifier = methodCall.getMethodExpression().getQualifierExpression();
            if (qualifier != null) {
              return ourGuard.doPreventingRecursion(qualifier, false, () -> getReflectiveType(qualifier));
            }
          }
          else if (arguments.length > 1 && isClassWithName(method.getContainingClass(), CommonClassNames.JAVA_LANG_REFLECT_ARRAY)) {
            final PsiExpression typeExpression = arguments[0];
            if (typeExpression != null) {
              final ReflectiveType itemType =
                ourGuard.doPreventingRecursion(typeExpression, false, () -> getReflectiveType(typeExpression));
              return ReflectiveType.arrayOf(itemType);
            }
          }
        }
      }
    }
    return ReflectiveType.create(expression.getType(), false);
  }

  @Contract("null,_->null")
  @Nullable
  public static <T> T computeConstantExpression(@Nullable PsiExpression expression, @NotNull Class<T> expectedType) {
    expression = ParenthesesUtils.stripParentheses(expression);
    final Object computed = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false);
    return ObjectUtils.tryCast(computed, expectedType);
  }

  @Nullable
  public static ReflectiveClass getReflectiveClass(PsiExpression context) {
    final ReflectiveType reflectiveType = getReflectiveType(context);
    return reflectiveType != null ? reflectiveType.getReflectiveClass() : null;
  }

  @Nullable
  public static PsiExpression findDefinition(@Nullable PsiExpression expression) {
    int preventEndlessLoop = 5;
    while (expression instanceof PsiReferenceExpression) {
      if (--preventEndlessLoop == 0) return null;
      expression = findVariableDefinition((PsiReferenceExpression)expression);
    }
    return expression;
  }

  @Nullable
  private static PsiExpression findVariableDefinition(@NotNull PsiReferenceExpression referenceExpression) {
    final PsiElement resolved = referenceExpression.resolve();
    return resolved instanceof PsiVariable ? findVariableDefinition(referenceExpression, (PsiVariable)resolved) : null;
  }

  @Nullable
  private static PsiExpression findVariableDefinition(@NotNull PsiReferenceExpression referenceExpression, @NotNull PsiVariable variable) {
    if (variable.hasModifierProperty(PsiModifier.FINAL)) {
      final PsiExpression initializer = variable.getInitializer();
      if (initializer != null) {
        return initializer;
      }
      if (variable instanceof PsiField) {
        return findFinalFieldDefinition(referenceExpression, (PsiField)variable);
      }
    }
    return DeclarationSearchUtils.findDefinition(referenceExpression, variable);
  }

  @Nullable
  private static PsiExpression findFinalFieldDefinition(@NotNull PsiReferenceExpression referenceExpression, @NotNull PsiField field) {
    if (!field.hasModifierProperty(PsiModifier.FINAL)) return null;
    final PsiClass psiClass = ObjectUtils.tryCast(field.getParent(), PsiClass.class);
    if (psiClass != null) {
      final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
      final List<PsiClassInitializer> initializers =
        ContainerUtil.filter(psiClass.getInitializers(), initializer -> initializer.hasModifierProperty(PsiModifier.STATIC) == isStatic);
      for (PsiClassInitializer initializer : initializers) {
        final PsiExpression assignedExpression = getAssignedExpression(initializer, field);
        if (assignedExpression != null) {
          return assignedExpression;
        }
      }
      if (!isStatic) {
        final PsiMethod[] constructors = psiClass.getConstructors();
        if (constructors.length == 1) {
          return getAssignedExpression(constructors[0], field);
        }
        for (PsiMethod constructor : constructors) {
          if (PsiTreeUtil.isAncestor(constructor, referenceExpression, true)) {
            return getAssignedExpression(constructor, field);
          }
        }
      }
    }
    return null;
  }

  @Nullable
  private static PsiExpression getAssignedExpression(@NotNull PsiMember maybeContainsAssignment, @NotNull PsiField field) {
    final PsiAssignmentExpression assignment = SyntaxTraverser.psiTraverser(maybeContainsAssignment)
      .filter(PsiAssignmentExpression.class)
      .find(expression -> ExpressionUtils.isReferenceTo(expression.getLExpression(), field));
    return assignment != null ? assignment.getRExpression() : null;
  }

  private static PsiClass findClass(@NotNull String qualifiedName, @NotNull PsiElement context) {
    final Project project = context.getProject();
    return JavaPsiFacade.getInstance(project).findClass(qualifiedName, GlobalSearchScope.allScope(project));
  }

  @Contract("null -> false")
  static boolean isJavaLangClass(@Nullable PsiClass aClass) {
    return isClassWithName(aClass, CommonClassNames.JAVA_LANG_CLASS);
  }

  @Contract("null -> false")
  static boolean isJavaLangObject(@Nullable PsiClass aClass) {
    return isClassWithName(aClass, CommonClassNames.JAVA_LANG_OBJECT);
  }

  @Contract("null, _ -> false")
  public static boolean isClassWithName(@Nullable PsiClass aClass, @NotNull String name) {
    return aClass != null && name.equals(aClass.getQualifiedName());
  }

  @Contract("null -> false")
  static boolean isRegularMethod(@Nullable PsiMethod method) {
    return method != null && !method.isConstructor();
  }

  static boolean isPublic(@NotNull PsiMember member) {
    return member.hasModifierProperty(PsiModifier.PUBLIC);
  }

  static boolean isAtomicallyUpdateable(@NotNull PsiField field) {
    if (field.hasModifierProperty(PsiModifier.STATIC) || !field.hasModifierProperty(PsiModifier.VOLATILE)) {
      return false;
    }
    final PsiType type = field.getType();
    return !(type instanceof PsiPrimitiveType) || PsiType.INT.equals(type) || PsiType.LONG.equals(type);
  }

  @Nullable
  static String getParameterTypesText(@NotNull PsiMethod method) {
    final StringJoiner joiner = new StringJoiner(", ");
    for (PsiParameter parameter : method.getParameterList().getParameters()) {
      final String typeText = getTypeText(parameter.getType());
      joiner.add(typeText + ".class");
    }
    return joiner.toString();
  }

  static void shortenArgumentsClassReferences(@NotNull InsertionContext context) {
    final PsiElement parameter = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset());
    final PsiExpressionList parameterList = PsiTreeUtil.getParentOfType(parameter, PsiExpressionList.class);
    if (parameterList != null && parameterList.getParent() instanceof PsiMethodCallExpression) {
      JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(parameterList);
    }
  }

  @NotNull
  static LookupElement withPriority(@NotNull LookupElement lookupElement, boolean hasPriority) {
    return hasPriority ? lookupElement : PrioritizedLookupElement.withPriority(lookupElement, -1);
  }

  @Nullable
  static LookupElement withPriority(@Nullable LookupElement lookupElement, int priority) {
    return priority == 0 || lookupElement == null ? lookupElement : PrioritizedLookupElement.withPriority(lookupElement, priority);
  }

  static int getMethodSortOrder(@NotNull PsiMethod method) {
    return isJavaLangObject(method.getContainingClass()) ? 1 : isPublic(method) ? -1 : 0;
  }

  @Nullable
  static String getMemberType(@Nullable PsiElement element) {
    final PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
    return methodCall != null ? methodCall.getMethodExpression().getReferenceName() : null;
  }

  @Nullable
  static LookupElement lookupMethod(@NotNull PsiMethod method, @Nullable InsertHandler<LookupElement> insertHandler) {
    final ReflectiveSignature signature = getMethodSignature(method);
    return signature != null
           ? LookupElementBuilder.create(signature, method.getName())
             .withIcon(signature.getIcon())
             .withTailText(signature.getShortArgumentTypes())
             .withInsertHandler(insertHandler)
           : null;
  }

  static void replaceText(@NotNull InsertionContext context, @NotNull String text) {
    final PsiElement newElement = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset());
    final PsiElement params = newElement.getParent().getParent();
    final int end = params.getTextRange().getEndOffset() - 1;
    final int start = Math.min(newElement.getTextRange().getEndOffset(), end);

    context.getDocument().replaceString(start, end, text);
    context.commitDocument();
    shortenArgumentsClassReferences(context);
  }

  @NotNull
  public static String getTypeText(@NotNull PsiType type) {
    final ReflectiveType reflectiveType = ReflectiveType.create(type, false);
    return reflectiveType.getQualifiedName();
  }

  @Nullable
  public static String getTypeText(@Nullable PsiExpression argument) {
    final ReflectiveType reflectiveType = getReflectiveType(argument);
    return reflectiveType != null ? reflectiveType.getQualifiedName() : null;
  }

  @Contract("null -> null")
  @Nullable
  public static ReflectiveSignature getMethodSignature(@Nullable PsiMethod method) {
    if (method != null) {
      final List<String> types = new ArrayList<>();
      final PsiType returnType = method.getReturnType();
      types.add(getTypeText(returnType != null ? returnType : PsiType.VOID)); // null return type means it's a constructor

      for (PsiParameter parameter : method.getParameterList().getParameters()) {
        types.add(getTypeText(parameter.getType()));
      }
      final Icon icon = method.getIcon(Iconable.ICON_FLAG_VISIBILITY);
      return ReflectiveSignature.create(icon, types);
    }
    return null;
  }

  @NotNull
  public static String getMethodTypeExpressionText(@NotNull ReflectiveSignature signature) {
    final String types = signature.getText(true, type -> type + ".class");
    return JAVA_LANG_INVOKE_METHOD_TYPE + "." + METHOD_TYPE + types;
  }

  public static boolean isCallToMethod(@NotNull PsiMethodCallExpression methodCall, @NotNull String className, @NotNull String methodName) {
    return MethodCallUtils.isCallToMethod(methodCall, className, null, methodName, (PsiType[])null);
  }

  /**
   * Tries to unwrap array and find its components
   * @param maybeArray an array to unwrap
   * @return list of unwrapped array components, some or all of them could be null if unknown (but the length is known);
   * returns null if nothing is known.
   */
  @Nullable
  public static List<PsiExpression> getVarargs(@Nullable PsiExpression maybeArray) {
    if (ExpressionUtils.isNullLiteral(maybeArray)) {
      return Collections.emptyList();
    }
    if (isVarargAsArray(maybeArray)) {
      final PsiExpression argumentsDefinition = findDefinition(maybeArray);
      if (argumentsDefinition instanceof PsiArrayInitializerExpression) {
        return Arrays.asList(((PsiArrayInitializerExpression)argumentsDefinition).getInitializers());
      }
      if (argumentsDefinition instanceof PsiNewExpression) {
        final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)argumentsDefinition).getArrayInitializer();
        if (arrayInitializer != null) {
          return Arrays.asList(arrayInitializer.getInitializers());
        }
        final PsiExpression[] dimensions = ((PsiNewExpression)argumentsDefinition).getArrayDimensions();
        if (dimensions.length == 1) { // new Object[length] or new Class<?>[length]
          final Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class);
          if (itemCount != null && itemCount >= 0 && itemCount < 256) {
            return Collections.nCopies(itemCount, null);
          }
        }
      }
    }
    return null;
  }

  @Contract("null -> false")
  public static boolean isVarargAsArray(@Nullable PsiExpression maybeArray) {
    final PsiType type = maybeArray != null ? maybeArray.getType() : null;
    return type instanceof PsiArrayType &&
           type.getArrayDimensions() == 1 &&
           type.getDeepComponentType() instanceof PsiClassType;
  }

  /**
   * Take method's return type and parameter types
   * from arguments of MethodType.methodType(Class...) and MethodType.genericMethodType(int, boolean?)
   */
  @Nullable
  public static ReflectiveSignature composeMethodSignature(@Nullable PsiExpression methodTypeExpression) {
    final PsiExpression typeDefinition = findDefinition(methodTypeExpression);
    if (typeDefinition instanceof PsiMethodCallExpression) {
      final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)typeDefinition;
      final String referenceName = methodCallExpression.getMethodExpression().getReferenceName();

      Function<PsiExpression[], ReflectiveSignature> composer = null;
      if (METHOD_TYPE.equals(referenceName)) {
        composer = JavaReflectionReferenceUtil::composeMethodSignatureFromTypes;
      }
      else if (GENERIC_METHOD_TYPE.equals(referenceName)) {
        composer = JavaReflectionReferenceUtil::composeGenericMethodSignature;
      }

      if (composer != null) {
        final PsiMethod method = methodCallExpression.resolveMethod();
        if (method != null) {
          final PsiClass psiClass = method.getContainingClass();
          if (psiClass != null && JAVA_LANG_INVOKE_METHOD_TYPE.equals(psiClass.getQualifiedName())) {
            final PsiExpression[] arguments = methodCallExpression.getArgumentList().getExpressions();
            return composer.apply(arguments);
          }
        }
      }
    }
    return null;
  }

  @Nullable
  private static ReflectiveSignature composeMethodSignatureFromTypes(PsiExpression @NotNull [] returnAndParameterTypes) {
    final List<String> typeTexts = ContainerUtil.map(returnAndParameterTypes, JavaReflectionReferenceUtil::getTypeText);
    return ReflectiveSignature.create(typeTexts);
  }

  @Nullable
  public static Pair.NonNull<Integer, Boolean> getGenericSignature(PsiExpression @NotNull [] genericSignatureShape) {
    if (genericSignatureShape.length == 0 || genericSignatureShape.length > 2) {
      return null;
    }

    final Integer objectArgCount = computeConstantExpression(genericSignatureShape[0], Integer.class);
    final Boolean finalArray = // there's an additional parameter which is an ellipsis or an array
      genericSignatureShape.length > 1 ? computeConstantExpression(genericSignatureShape[1], Boolean.class) : false;

    if (objectArgCount == null || objectArgCount < 0 || objectArgCount > 255) {
      return null;
    }
    if (finalArray == null || finalArray && objectArgCount > 254) {
      return null;
    }
    return Pair.createNonNull(objectArgCount, finalArray);
  }

  /**
   * All the types in the method signature are either unbounded type parameters or java.lang.Object (with possible vararg)
   */
  @Nullable
  private static ReflectiveSignature composeGenericMethodSignature(PsiExpression @NotNull [] genericSignatureShape) {
    final Pair.NonNull<Integer, Boolean> signature = getGenericSignature(genericSignatureShape);
    if (signature == null) return null;
    final int objectArgCount = signature.getFirst();
    final boolean finalArray = signature.getSecond();

    final List<String> typeNames = new ArrayList<>();
    typeNames.add(CommonClassNames.JAVA_LANG_OBJECT); // return type

    for (int i = 0; i < objectArgCount; i++) {
      typeNames.add(CommonClassNames.JAVA_LANG_OBJECT);
    }
    if (finalArray) {
      typeNames.add(CommonClassNames.JAVA_LANG_OBJECT + "[]");
    }
    return ReflectiveSignature.create(typeNames);
  }

  public static class ReflectiveType {
    final PsiType myType;
    final boolean myIsExact;

    private ReflectiveType(@NotNull PsiType erasedType, boolean isExact) {
      myType = erasedType;
      myIsExact = isExact;
    }

    @NotNull
    public String getQualifiedName() {
      return myType.getCanonicalText();
    }

    @Override
    public String toString() {
      return myType.getCanonicalText();
    }

    public boolean isEqualTo(@Nullable PsiType otherType) {
      return otherType != null && myType.equals(erasure(otherType));
    }

    public boolean isAssignableFrom(@NotNull PsiType type) {
      return myType.isAssignableFrom(type);
    }

    public boolean isPrimitive() {
      return myType instanceof PsiPrimitiveType;
    }

    @NotNull
    public PsiType getType() {
      return myType;
    }

    public boolean isExact() {
      return myIsExact;
    }

    @Nullable
    public ReflectiveClass getReflectiveClass() {
      PsiClass psiClass = getPsiClass();
      if (psiClass != null) {
        return new ReflectiveClass(psiClass, myIsExact);
      }
      return null;
    }

    @Nullable
    public ReflectiveType getArrayComponentType() {
      if (myType instanceof PsiArrayType) {
        PsiType componentType = ((PsiArrayType)myType).getComponentType();
        return new ReflectiveType(componentType, myIsExact);
      }
      return null;
    }

    @Nullable
    public PsiClass getPsiClass() {
      return PsiTypesUtil.getPsiClass(myType);
    }

    @Contract("!null,_ -> !null; null,_ -> null")
    @Nullable
    public static ReflectiveType create(@Nullable PsiType originalType, boolean isExact) {
      if (originalType != null) {
        return new ReflectiveType(erasure(originalType), isExact);
      }
      return null;
    }

    @Contract("!null,_ -> !null; null,_ -> null")
    @Nullable
    public static ReflectiveType create(@Nullable PsiClass psiClass, boolean isExact) {
      if (psiClass != null) {
        final PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject());
        return new ReflectiveType(factory.createType(psiClass), isExact);
      }
      return null;
    }

    @Contract("!null -> !null; null -> null")
    @Nullable
    public static ReflectiveType arrayOf(@Nullable ReflectiveType itemType) {
      if (itemType != null) {
        return new ReflectiveType(itemType.myType.createArrayType(), itemType.myIsExact);
      }
      return null;
    }

    @NotNull
    private static PsiType erasure(@NotNull PsiType type) {
      final PsiType erasure = TypeConversionUtil.erasure(type);
      if (erasure instanceof PsiEllipsisType) {
        return ((PsiEllipsisType)erasure).toArrayType();
      }
      return erasure;
    }
  }

  public static class ReflectiveClass {
    final PsiClass myPsiClass;
    final boolean myIsExact;

    public ReflectiveClass(@NotNull PsiClass psiClass, boolean isExact) {
      myPsiClass = psiClass;
      myIsExact = isExact;
    }

    @NotNull
    public PsiClass getPsiClass() {
      return myPsiClass;
    }

    public boolean isExact() {
      return myIsExact || myPsiClass.hasModifierProperty(PsiModifier.FINAL);
    }
  }

  public static class ReflectiveSignature implements Comparable<ReflectiveSignature> {
    public static final ReflectiveSignature NO_ARGUMENT_CONSTRUCTOR_SIGNATURE =
      new ReflectiveSignature(null, PsiKeyword.VOID, ArrayUtilRt.EMPTY_STRING_ARRAY);

    private final Icon myIcon;
    @NotNull private final String myReturnType;
    private final String @NotNull [] myArgumentTypes;

    @Nullable
    public static ReflectiveSignature create(@NotNull List<String> typeTexts) {
      return create(null, typeTexts);
    }

    @Nullable
    public static ReflectiveSignature create(@Nullable Icon icon, @NotNull List<String> typeTexts) {
      if (!typeTexts.isEmpty() && !typeTexts.contains(null)) {
        final String[] argumentTypes = ArrayUtilRt.toStringArray(typeTexts.subList(1, typeTexts.size()));
        return new ReflectiveSignature(icon, typeTexts.get(0), argumentTypes);
      }
      return null;
    }

    private ReflectiveSignature(@Nullable Icon icon, @NotNull String returnType, String @NotNull [] argumentTypes) {
      myIcon = icon;
      myReturnType = returnType;
      myArgumentTypes = argumentTypes;
    }

    public String getText(boolean withReturnType, @NotNull Function<? super String, String> transformation) {
      return getText(withReturnType, true, transformation);
    }

    public String getText(boolean withReturnType, boolean withParentheses, @NotNull Function<? super String, String> transformation) {
      final StringJoiner joiner = new StringJoiner(", ", withParentheses ? "(" : "", withParentheses ? ")" : "");
      if (withReturnType) {
        joiner.add(transformation.apply(myReturnType));
      }
      for (String argumentType : myArgumentTypes) {
        joiner.add(transformation.apply(argumentType));
      }
      return joiner.toString();
    }

    @NotNull
    public String getShortReturnType() {
      return PsiNameHelper.getShortClassName(myReturnType);
    }

    @NotNull
    public String getShortArgumentTypes() {
      return getText(false, PsiNameHelper::getShortClassName);
    }

    @Nullable
    public Icon getIcon() {
      return myIcon != null ? myIcon : PlatformIcons.METHOD_ICON;
    }

    @Override
    public int compareTo(@NotNull ReflectiveSignature other) {
      int c = myArgumentTypes.length - other.myArgumentTypes.length;
      if (c != 0) return c;
      c = ArrayUtil.lexicographicCompare(myArgumentTypes, other.myArgumentTypes);
      if (c != 0) return c;
      return myReturnType.compareTo(other.myReturnType);
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (!(o instanceof ReflectiveSignature)) return false;
      final ReflectiveSignature other = (ReflectiveSignature)o;
      return Objects.equals(myReturnType, other.myReturnType) &&
             Arrays.equals(myArgumentTypes, other.myArgumentTypes);
    }

    @Override
    public int hashCode() {
      return Objects.hash(myReturnType, myArgumentTypes);
    }

    @Override
    public String toString() {
      return myReturnType + " " + Arrays.toString(myArgumentTypes);
    }
  }
}


text:
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.context.servlet;

import java.util.Enumeration;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * HttpServletRequest Cookies as Map.
 *
 * @author Dimitry D'hondt
 * @author Anton Koinov
 * @version $Revision: 472618 $ $Date: 2006-11-08 21:06:54 +0100 (Mi, 08 Nov 2006) $
 */
public class CookieMap extends AbstractAttributeMap
{
    private static final Cookie[] EMPTY_ARRAY = new Cookie[0];

    final HttpServletRequest _httpServletRequest;

    CookieMap(HttpServletRequest httpServletRequest)
    {
        _httpServletRequest = httpServletRequest;
    }

    public void clear()
    {
        throw new UnsupportedOperationException(
            "Cannot clear HttpRequest Cookies");
    }

    public boolean containsKey(Object key)
    {
        Cookie[] cookies = _httpServletRequest.getCookies();
        if (cookies == null) return false;
        for (int i = 0, len = cookies.length; i < len; i++)
        {
            if (cookies[i].getName().equals(key))
            {
                return true;
            }
        }

        return false;
    }

    public boolean containsValue(Object findValue)
    {
        if (findValue == null)
        {
            return false;
        }

        Cookie[] cookies = _httpServletRequest.getCookies();
        if (cookies == null) return false;
        for (int i = 0, len = cookies.length; i < len; i++)
        {
            if (findValue.equals(cookies[i]))
            {
                return true;
            }
        }

        return false;
    }

    public boolean isEmpty()
    {
        Cookie[] cookies = _httpServletRequest.getCookies();
        return cookies == null || cookies.length == 0;
    }

    public int size()
    {
        Cookie[] cookies = _httpServletRequest.getCookies();
        return cookies == null ? 0 : cookies.length;
    }

    public void putAll(Map t)
    {
        throw new UnsupportedOperationException();
    }

    protected Object getAttribute(String key)
    {
        Cookie[] cookies = _httpServletRequest.getCookies();
        if (cookies == null) return null;
        for (int i = 0, len = cookies.length; i < len; i++)
        {
            if (cookies[i].getName().equals(key))
            {
                return cookies[i];
            }
        }

        return null;
    }

    protected void setAttribute(String key, Object value)
    {
        throw new UnsupportedOperationException(
            "Cannot set HttpRequest Cookies");
    }

    protected void removeAttribute(String key)
    {
        throw new UnsupportedOperationException(
            "Cannot remove HttpRequest Cookies");
    }

    protected Enumeration getAttributeNames()
    {
        Cookie[] cookies = _httpServletRequest.getCookies();
        if (cookies == null)
        {
            return new CookieNameEnumeration(EMPTY_ARRAY);
        }
        else
        {
            return new CookieNameEnumeration(cookies);
        }
    }

    private static class CookieNameEnumeration implements Enumeration
    {
        private final Cookie[] _cookies;
        private final int _length;
        private int _index;

        public CookieNameEnumeration(Cookie[] cookies)
        {
            _cookies = cookies;
            _length = cookies.length;
        }

        public boolean hasMoreElements()
        {
            return _index < _length;
        }

        public Object nextElement()
        {
            return _cookies[_index++].getName();
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
module HoptoadNotifier
  VERSION = "2.3.5".freeze
end


text:
name              'openvpn'
maintainer        'Xhost Australia'
maintainer_email  'cookbooks@xhost.com.au'
license           'Apache 2.0'
description       'Installs and configures openvpn and includes rake tasks for managing certs.'
long_description  IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version           '2.1.1'

recipe 'openvpn::default',              'Installs OpenVPN only (no configuration).'
recipe 'openvpn::install',              'Installs OpenVPN only (no configuration).'
recipe 'openvpn::server',               'Installs and configures OpenVPN as a server.'
recipe 'openvpn::client',               'Installs and configures OpenVPN as a client.'
recipe 'openvpn::service',              'Manages the OpenVPN system service.'
recipe 'openvpn::users',                'Sets up openvpn cert/configs for users data bag items.'
recipe 'openvpn::install_bridge_utils', 'Installs bridge utilities for Linux.'

depends 'apt'
depends 'yum', '~> 3.0'
depends 'yum-epel'

supports 'arch'
supports 'centos'
supports 'debian'
supports 'fedora'
supports 'redhat'
supports 'ubuntu'

attribute 'openvpn/config/local',
          display_name: 'OpenVPN Local',
          description:  'Local interface (ip) to listen on',
          default:      nil,
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/config/proto',
          display_name: 'OpenVPN Protocol',
          description:  'The transport protocol to use for OpenVPN (UDP or TCP)',
          default:      'udp',
          choice:       %w(udp tcp),
          recipes:      ['openvpn::default', 'openvpn::server', 'openvpn::client']

attribute 'openvpn/type',
          display_name: 'OpenVPN Type',
          description:  'Server or server-bridge',
          default:      'server',
          choice:       ['server', 'server-bridge'],
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/subnet',
          display_name: 'OpenVPN Subnet',
          description:  'Subnet to hand out to clients',
          default:      '10.8.0.0',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/netmask',
          display_name: 'OpenVPN Netmask',
          description:  'Netmask for clients',
          default:      '255.255.0.0',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/config/port',
          display_name: 'OpenVPN Listen Port',
          description:  'Port to listen on, defaults to 1194',
          default:      '1194',
          choice:       %w(1194 443 80 1024),
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/gateway',
          display_name: 'OpenVPN Gateway FQDN',
          description:  'FQDN for the VPN gateway server. Default is vpn.domain',
          recipes:      ['openvpn::default', 'openvpn::client']

attribute 'openvpn/config/log',
          display_name: 'OpenVPN Log File',
          description:  'OpenVPN Server log file. Default /var/log/openvpn.log',
          default:      '/var/log/openvpn.log',
          recipes:      ['openvpn::default', 'openvpn::server', 'openvpn::client']

attribute 'openvpn/key_dir',
          display_name: 'OpenVPN Key Directory',
          description:  'Location to store keys, certificates and related files. '\
                        'Default: /etc/openvpn/keys',
          default:      '/etc/openvpn/keys',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/signing_ca_cert',
          display_name: 'OpenVPN CA Certificate',
          description:  'CA certificate for signing, default /etc/openvpn/keys/ca.crt',
          default:      '/etc/openvpn/keys/ca.crt',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/signing_ca_key',
          display_name: 'OpenVPN CA key',
          description:  'CA key for signing, default /etc/openvpn/keys/ca.key',
          default:      '/etc/openvpn/keys/ca.key',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/push_options',
          display_name: 'OpenVPN Push DHCP Options',
          description:  'An array of DHCP options to push to clients from the server.conf. '\
                        'Default is empty.',
          type:         'array',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/push_routes',
          display_name: 'OpenVPN Push Routes',
          description:  'An array of routes to push to clients from the server.conf. '\
                        'Default is empty.',
          type:         'array',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/script_security',
          display_name: 'OpenVPN Script Security',
          description:  'Script Security setting to use in server config. '\
                        'Default is 1. The "up" script will not be included if this is 0 or 1. '\
                        'Set it to 2 to use the "up" script',
          default:      '1',
          recipes:      ['openvpn::default', 'openvpn::server']

attribute 'openvpn/configure_default_server',
          display_name: 'Configure Default Server',
          description:  'Boolean to determine whether the default recipe will create a "conf" '\
                        'file for the default server. Set to false if you want to use only the '\
                        'LWRP to create the conf files.',
          default:      'true',
          recipes:      ['openvpn::default', 'openvpn::server', 'openvpn::client']

attribute 'openvpn/key/ca_expire',
          display_name: 'OpenVPN Root CA Expiry',
          description:  'In how many days should the root CA key expire',
          default:      '3650',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/expire',
          display_name: 'OpenVPN Certificate Expiry',
          description:  'In how many days should certificates expire',
          default:      '3650',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/size',
          display_name: 'OpenVPN Key Size',
          description:  'Default key size, set to 2048 if paranoid but will slow down '\
                        'TLS negotiation performance',
          default:      '1024',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/country',
          display_name: 'OpenVPN Certificate Country',
          description:  'The country for the TLS certificate',
          default:      'US',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/province',
          display_name: 'OpenVPN Certificate Province',
          description:  'The province for the TLS certificate',
          default:      'CA',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/city',
          display_name: 'OpenVPN Certificate City',
          description:  'The city for the TLS certificate',
          default:      'San Francisco',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/org',
          display_name: 'OpenVPN Certificate Organization',
          description:  'The organization name for the TLS certificate',
          default:      'Fort-Funston',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']

attribute 'openvpn/key/email',
          display_name: 'OpenVPN Certificate Email',
          description:  'The email address for the TLS certificate',
          default:      'me@example.com',
          recipes:      ['openvpn::default', 'openvpn::users', 'openvpn::server']


text:
using System;

internal class Account
{
    public decimal Balance { get; set; }

    public bool CanWithdraw(int amount)
    {
        return amount <= Balance;
    }

    public void Withdraw(int amount)
    {
        throw new Exception();
        //if (amount < 0) throw new InvalidOperationException();
    }
}


text:
import logging
from pprint import pprint
import hashlib

from adwords_client.client import AdWords
from adwords_client import reports
from adwords_client.internal_api.builder import OperationsBuilder
from datetime import datetime

logging.basicConfig(level=logging.INFO)
logging.getLogger('googleads').setLevel(logging.ERROR)
logging.getLogger('oauth2client').setLevel(logging.ERROR)
logging.getLogger('suds').setLevel(logging.WARNING)
logging.getLogger('zeep').setLevel(logging.WARNING)

def _delete_campaigns():
    client = AdWords(workdir='./tests/generated_files')
    new_report_df = reports.get_campaigns_report(client, 7857288943, 'CampaignStatus != "REMOVED"', fields=True)
    for campaign in new_report_df:
        entry = {
            'object_type': 'campaign',
            'client_id': 7857288943,
            'campaign_id': campaign['CampaignId'],
            'campaign_name': 'API test campaign',
            'operator': 'SET',
            'status': 'REMOVED',
        }
        client.insert(entry)
    operations_folder = client.split()
    client.execute_operations(operations_folder)
    return client.wait_jobs(operations_folder)

def _create_campaign():
    client = AdWords(workdir='./tests/generated_files')
    client.insert(
        {
            'object_type': 'campaign',
            'client_id': 7857288943,
            'campaign_id': -1,
            'budget': 1000,
            'campaign_name': 'API test campaign',
            'locations': [1001773, 1001768],  # Sao Paulo, Sao Caetano
            'languages': [1014, 1000],  # Portuguese, English
            'status': 'PAUSED',
        }
    )
    client.insert(
        {
            'object_type': 'adgroup',
            'client_id': 7857288943,
            'campaign_id': -1,
            'adgroup_id': -2,
            'adgroup_name': 'API test adgroup',
            'cpc_bid': 13.37,
        }
    )
    client.insert(
        {
            'object_type': 'keyword',
            'client_id': 7857288943,
            'campaign_id': -1,
            'adgroup_id': -2,
            'text': 'my search term',
            'keyword_match_type': 'broad',
            'status': 'PAUSED',
            'cpc_bid': 13.37,
        }
    )
    client.insert(
        {
            'object_type': 'ad',
            'client_id': 7857288943,
            'campaign_id': -1,
            'adgroup_id': -2,
            'headline_part_1': 'Ad test',
            'headline_part_2': 'my pretty test',
            'description': 'This is my test ad',
            'path_1': 'test',
            'path_2': 'ad',
            'final_urls': 'http://www.mytest.com/',
            'final_mobile_urls': 'http://m.mytest.com/',
        }
    )
    operations_folder = client.split()
    client.execute_operations(operations_folder)
    return client.wait_jobs(operations_folder)

def _get_keywords_report(client=None):
    client = client or AdWords()
    report_df = reports.get_keywords_report(client, 7857288943, 'CampaignStatus = "PAUSED"', fields=True)
    return report_df

def _get_adgroups_report(client=None):
    client = client or AdWords()
    report_df = reports.get_adgroups_report(client, 7857288943, 'CampaignStatus = "PAUSED"', fields=True)
    return report_df

def _adjust_bids():
    client = AdWords(workdir='./tests/generated_files')

    for keyword in _get_keywords_report(client):
        entry = {
            'object_type': 'keyword',
            'cpc_bid': 4.20,
            'client_id': keyword['ExternalCustomerId'],
            'campaign_id': keyword['CampaignId'],
            'adgroup_id': keyword['AdGroupId'],
            'criteria_id': keyword['Id'],
            'operator': 'SET',
        }
        client.insert(entry)

    for adgroup in _get_adgroups_report(client):
        entry = {
            'object_type': 'adgroup',
            'cpc_bid': 4.20,
            'client_id': adgroup['ExternalCustomerId'],
            'campaign_id': adgroup['CampaignId'],
            'adgroup_id': adgroup['AdGroupId'],
            'operator': 'SET',
        }
        client.insert(entry)

    operations_folder = client.split()
    client.execute_operations(operations_folder)
    return client.wait_jobs(operations_folder)

def _sync_operations():
    client = AdWords()

    get_internal_operation = {
        'object_type': 'shared_set',
        'client_id': 7857288943,
        'fields': ['Name', 'SharedSetId', 'Type', 'Status'],
        'predicates': [
            ('Name', 'EQUALS', 'API Sync Test'),
            ('Status', 'EQUALS', 'ENABLED'),
        ]
    }
    shared_sets = client.get_entities(get_internal_operation)
    for shared_set in shared_sets:
        client.insert({
            'object_type': 'shared_set',
            'client_id': 7857288943,
            'shared_set_id': shared_set['sharedSetId'],
            'operator': 'REMOVE'
        })

    client.execute_operations(sync=True)

    client.insert({
        'object_type': 'shared_set',
        'client_id': 7857288943,
        'shared_set_name': 'API Sync Test',
        'shared_set_type': 'NEGATIVE_KEYWORDS',
    })

    client.execute_operations(sync=True)

    shared_sets = client.get_entities(get_internal_operation)

    for shared_set in shared_sets:
        client.insert({
            'object_type': 'shared_set',
            'client_id': 7857288943,
            'shared_set_id': shared_set['sharedSetId'],
            'operator': 'REMOVE'
        })

    client.execute_operations(sync=True)

def _build_shared_set_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'shared_set',
        'client_id': 7857288943,
        'fields': ['Name', 'SharedSetId', 'Type', 'Status'],
        'predicates': [
            ('Name', 'EQUALS', 'API Sync Test'),
            ('Status', 'IN', ['ENABLED']),
        ]
    }

    get_adwords_operation = next(operation_builder(get_internal_operation))

    expected_get_adwords_operation = {
        'fields': ['Name', 'SharedSetId', 'Type', 'Status'],
        'ordering': [], 'xsi_type': 'Selector',
        'predicates': [
            {
                'values': ['API Sync Test'],
                'field': 'Name',
                'operator': 'EQUALS',
                'xsi_type': 'Predicate'
            },
            {
                'values': ['ENABLED'],
                'field': 'Status',
                'operator': 'IN', 'xsi_type': 'Predicate'
            }
        ],
        'paging': {
            'numberResults': 10000,
            'startIndex': 0,
            'xsi_type': 'Paging'
        }
    }
    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])

    assert expected_get_adwords_operation == get_adwords_operation

def _build_budget_order_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'budget_order',
        'client_id': 7857288943,
        'fields': ['BillingAccountId', 'PrimaryBillingId', 'Id', 'BillingAccountName'],
        'predicates': [
            ('billingAccountName', 'EQUALS', 'Billing Account Test'),
            ('PrimaryBillingId', 'EQUALS', "1234-5678-9012"),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'ordering': [],
        'predicates': [
            {
                'values': ['Billing Account Test'],
                'xsi_type': 'Predicate',
                'field': 'billingAccountName',
                'operator': 'EQUALS'},
            {
                'values': ['1234-5678-9012'],
                'xsi_type': 'Predicate',
                'field': 'PrimaryBillingId',
                'operator': 'EQUALS'
            }],
        'xsi_type': 'Selector',
        'fields': ['BillingAccountId', 'PrimaryBillingId', 'Id', 'BillingAccountName'],
        'paging': {'startIndex': 0, 'numberResults': 10000, 'xsi_type': 'Paging'}
    }
    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    start_date_time = datetime(2018, 12, 30, 23, 59, 59)
    end_date_time = datetime(2037, 12, 30, 23, 59, 59)
    time_zone = 'America/Sao_Paulo'

    mutate_internal_operation = {
        'object_type': 'budget_order',
        'client_id': 7857288943,
        'billing_account_id': '1234-5678-9012-3456',
        'primary_billing_id': '1234-5678-9012',
        'start_date_time': start_date_time.isoformat(),
        'end_date_time': end_date_time.isoformat(),
        'time_zone': time_zone,
        'spending_limit': 10000,
        'po_number': 'My Test Reference',
        'budget_order_name': 'Budget Order Name Test',
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))

    expected_mutate_adwords_operation = {
        'xsi_type': 'BudgetOrderOperation',
        'operand':
            {
                'budgetOrderName': 'Budget Order Name Test',
                'startDateTime': format(start_date_time, '%Y%m%d %H%M%S ') + time_zone,
                'billingAccountId': '1234-5678-9012-3456',
                'poNumber': 'My Test Reference',
                'spendingLimit': {'microAmount': 10000},
                'endDateTime': format(end_date_time, '%Y%m%d %H%M%S ') + time_zone,
                'primaryBillingId': '1234-5678-9012'
            },
        'operator': 'ADD'
    }

    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_site_link_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_sitelink',
        'client_id': 7857288943,
        'fields': ['CampaignId', 'Extensions'],
        'predicates': [
            ('CampaignId', 'EQUALS', 213213123),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))

    expected_get_adwords_operation = {
        'ordering': [],
        'xsi_type': 'Selector',
        'predicates': [{
            'xsi_type': 'Predicate',
            'values': [213213123],
            'field': 'CampaignId',
            'operator': 'EQUALS'
        }, {
            'xsi_type': 'Predicate',
            'values': ['SITELINK'],
            'field': 'ExtensionType',
            'operator': 'EQUALS'
        }],
        'paging': {
            'xsi_type': 'Paging',
            'numberResults': 10000,
            'startIndex': 0
        },
        'fields': ['CampaignId', 'Extensions']
    }

    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'campaign_sitelink',
        'client_id': 343434324,
        'sitelinks_configuration':
            [
                {
                    'sitelink_text': 'Test 1',
                    'sitelink_final_url': 'https://www.example.com.br/'
                },
                {
                    'sitelink_text': 'Test 2',
                    'sitelink_final_url': 'https://www.example.com.br/example'
                },
                {
                    'sitelink_text': 'Test 3',
                    'sitelink_final_url': 'https://www.example.com.br/example'
                }
            ],
        'campaign_id': 343243243,
    }

    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))

    expected_mutate_adwords_operation = {
        'operator': 'ADD',
        'xsi_type': 'CampaignExtensionSettingOperation',
        'operand': {
            'xsi_type': 'CampaignExtensionSetting',
            'extensionType': 'SITELINK',
            'campaignId': 343243243,
            'extensionSetting':
                {
                    'extensions': [
                        {
                            'sitelinkFinalUrls':
                                {
                                    'urls': ['https://www.example.com.br/']
                                },
                            'xsi_type': 'SitelinkFeedItem',
                            'sitelinkText': 'Test 1'
                        },
                        {
                            'sitelinkFinalUrls':
                                {
                                    'urls': ['https://www.example.com.br/example']
                                },
                            'xsi_type': 'SitelinkFeedItem',
                            'sitelinkText': 'Test 2'
                        },
                        {
                            'sitelinkFinalUrls':
                                {
                                    'urls': ['https://www.example.com.br/example']
                                },
                            'xsi_type': 'SitelinkFeedItem',
                            'sitelinkText': 'Test 3'
                        }
                    ]
                }
        }
    }

    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_structured_snipppet_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_structured_snippet',
        'client_id': 7857288943,
        'fields': ['CampaignId', 'Extensions'],
        'predicates': [
            ('CampaignId', 'EQUALS', 213213123),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'ordering': [],
        'xsi_type': 'Selector',
        'predicates': [{
            'xsi_type': 'Predicate',
            'values': [213213123],
            'field': 'CampaignId',
            'operator': 'EQUALS'
        }, {
            'xsi_type': 'Predicate',
            'values': ['STRUCTURED_SNIPPET'],
            'field': 'ExtensionType',
            'operator': 'EQUALS'
        }],
        'paging': {
            'xsi_type': 'Paging',
            'numberResults': 10000,
            'startIndex': 0
        },
        'fields': ['CampaignId', 'Extensions']
    }
    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'campaign_structured_snippet',
        'client_id': 545545354,
        'snippets_configuration': [{
            'header': 'Serviços',
            'values': ['Construção', 'Manutenção', 'Conserto'],
        }],
        'campaign_id': 3232343242
    }

    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))

    expected_mutate_adwords_operation = {
        'xsi_type': 'CampaignExtensionSettingOperation',
        'operator': 'ADD',
        'operand': {
            'extensionSetting': {
                'extensions': [
                    {
                        'xsi_type': 'StructuredSnippetFeedItem',
                        'values': ['Construção', 'Manutenção', 'Conserto'],
                        'header': 'Serviços'
                    }
                ]
            },
            'xsi_type': 'CampaignExtensionSetting',
            'campaignId': 3232343242,
            'extensionType': 'STRUCTURED_SNIPPET'
        }
    }
    mutate_adwords_operation['operand']['extensionSetting']['extensions'][0]['values'] \
        = sorted(mutate_adwords_operation['operand']['extensionSetting']['extensions'][0]['values'])
    expected_mutate_adwords_operation['operand']['extensionSetting']['extensions'][0]['values'] \
        = sorted(expected_mutate_adwords_operation['operand']['extensionSetting']['extensions'][0]['values'])
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_callout_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_callout',
        'client_id': 7857288943,
        'fields': ['CampaignId', 'Extensions'],
        'predicates': [
            ('CampaignId', 'EQUALS', 213213123),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))

    expected_get_adwords_operation = {
        'ordering': [],
        'xsi_type': 'Selector',
        'predicates': [{
            'xsi_type': 'Predicate',
            'values': [213213123],
            'field': 'CampaignId',
            'operator': 'EQUALS'
        }, {
            'xsi_type': 'Predicate',
            'values': ['CALLOUT'],
            'field': 'ExtensionType',
            'operator': 'EQUALS'
        }],
        'paging': {
            'xsi_type': 'Paging',
            'numberResults': 10000,
            'startIndex': 0
        },
        'fields': ['CampaignId', 'Extensions']
    }
    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'campaign_callout',
        'client_id': 9973876376,
        'callout_text_list': ['Clique aqui', 'Somos Legais', 'Contrate aqui'],
        'campaign_id': 1341876198
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operand': {
            'campaignId': 1341876198,
            'extensionType': 'CALLOUT',
            'xsi_type': 'CampaignExtensionSetting',
            'extensionSetting': {
                'extensions': [
                    {
                        'xsi_type': 'CalloutFeedItem',
                        'calloutText': 'Clique aqui'
                    },
                    {
                        'xsi_type': 'CalloutFeedItem',
                        'calloutText': 'Somos Legais'
                    },
                    {
                        'xsi_type': 'CalloutFeedItem',
                        'calloutText': 'Contrate aqui'
                    }
                ]
            }
        },
        'operator': 'ADD',
        'xsi_type': 'CampaignExtensionSettingOperation'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_campaign_ad_schedule_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_ad_schedule',
        'client_id': 7857288943,
        'fields': ['CampaignId'],
        'predicates': [
            ('CampaignId', 'EQUALS', 213213123),
        ]
    }

    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'ordering': [],
        'paging': {
            'numberResults': 10000,
            'xsi_type': 'Paging',
            'startIndex': 0
        },
        'xsi_type': 'Selector',
        'fields': ['CampaignId'],
        'predicates': [{
            'field': 'CampaignId',
            'values': [213213123],
            'xsi_type': 'Predicate',
            'operator': 'EQUALS'
        }, {
            'field': 'CriteriaType',
            'values': ['AD_SCHEDULE'],
            'xsi_type': 'Predicate',
            'operator': 'EQUALS'
        }]
    }
    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'campaign_ad_schedule',
        'client_id': 3434324334,
        'day_of_week': 'MONDAY',
        'start_hour': 8,
        'start_minute': 23,
        'end_hour': 9,
        'end_minute': 33,
        'bid_modifier': 0.3,
        'campaign_id': 3353453453,
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operand': {
            'criterion': {
                'endMinute': 33,
                'startMinute': 23,
                'xsi_type': 'AdSchedule',
                'endHour': 9,
                'dayOfWeek': 'MONDAY',
                'startHour': 8,
            },
            'xsi_type': 'CampaignCriterion',
            'bidModifier': 0.3,
            'campaignId': 3353453453
        },
        'xsi_type': 'CampaignCriterionOperation',
        'operator': 'ADD'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_get_campaign_criterion_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_language',
        'client_id': 9973876376,
        'fields': ['CampaignId', 'Id'],
        'predicates': [
            ('CampaignId', 'EQUALS', 213213123),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'fields': ['CampaignId', 'Id'],
        'ordering': [],
        'xsi_type': 'Selector',
        'predicates': [{
            'operator': 'EQUALS',
            'xsi_type': 'Predicate',
            'field': 'CampaignId',
            'values': [213213123]
        }, {
            'operator': 'EQUALS',
            'xsi_type': 'Predicate',
            'field': 'CriteriaType',
            'values': ['LANGUAGE']
        }],
        'paging': {'startIndex': 0, 'numberResults': 10000, 'xsi_type': 'Paging'}
    }

    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    get_internal_operation = {
        'object_type': 'campaign_targeted_location',
        'client_id': 9973876376,
        'fields': ['CampaignId', 'Id'],
        'predicates': [
            ('CampaignId', 'EQUALS', 213213123),
        ]
    }
    expected_get_adwords_operation = {
        'fields': ['CampaignId', 'Id'],
        'ordering': [],
        'xsi_type': 'Selector',
        'predicates': [{
            'operator': 'EQUALS',
            'xsi_type': 'Predicate',
            'field': 'CampaignId',
            'values': [213213123]
        }, {
            'operator': 'EQUALS',
            'xsi_type': 'Predicate',
            'field': 'CriteriaType',
            'values': ['LOCATION']
        }],
        'paging': {'startIndex': 0, 'numberResults': 10000, 'xsi_type': 'Paging'}
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))

    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

def _build_shared_set_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'shared_set',
        'client_id': 7857288943,
        'fields': ['Name', 'SharedSetId', 'Type', 'Status'],
        'predicates': [
            ('Name', 'EQUALS', 'API Sync Test'),
            ('Status', 'EQUALS', 'ENABLED')
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'ordering': [],
        'predicates': [{
            'operator': 'EQUALS',
            'values': ['API Sync Test'],
            'xsi_type': 'Predicate',
            'field': 'Name'
        }, {
            'operator': 'EQUALS',
            'values': ['ENABLED'],
            'xsi_type': 'Predicate',
            'field': 'Status'}
        ],
        'xsi_type': 'Selector',
        'fields': ['Name', 'SharedSetId', 'Type', 'Status'],
        'paging': {'startIndex': 0, 'xsi_type': 'Paging', 'numberResults': 10000}
    }
    get_adwords_operation['predicates'] = sorted(get_adwords_operation['predicates'], key=lambda x: x['field'])
    expected_get_adwords_operation['predicates'] = sorted(
        expected_get_adwords_operation['predicates'], key=lambda x: x['field']
    )
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'shared_set',
        'client_id': 7857288943,
        'shared_set_name': 'API Sync Test',
        'shared_set_type': 'NEGATIVE_KEYWORDS',
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'xsi_type': 'SharedSetOperation',
        'operator': 'ADD',
        'operand': {
            'xsi_type': 'SharedSet',
            'name': 'API Sync Test',
            'type': 'NEGATIVE_KEYWORDS'
        }
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_campaign_shared_set_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_shared_set',
        'fields': ['CampaignId', 'SharedSetId'],
        'predicates': [
            ('CampaignId', 'EQUALS', 35345353534),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'ordering': [],
        'fields': ['CampaignId', 'SharedSetId'],
        'xsi_type': 'Selector',
        'predicates': [{
            'operator': 'EQUALS',
            'xsi_type': 'Predicate',
            'values': [35345353534],
            'field': 'CampaignId'}],
        'paging': {'numberResults': 10000, 'xsi_type': 'Paging', 'startIndex': 0}}

    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'campaign_shared_set',
        'client_id': 5543543543,
        'campaign_id': 455353535,
        'shared_set_id': 3453535545
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operand': {
            'xsi_type': 'CampaignSharedSet',
            'sharedSetId': 3453535545,
            'campaignId': 455353535
        },
        'xsi_type': 'CampaignSharedSetOperation',
        'operator': 'ADD'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_shared_criterion_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'shared_criterion',
        'fields': ['Id', 'SharedSetId'],
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    expected_get_adwords_operation = {
        'fields': ['Id', 'SharedSetId'],
        'xsi_type': 'Selector',
        'paging': {
            'xsi_type': 'Paging',
            'startIndex': 0,
            'numberResults': 10000
        },
        'ordering': [],
        'predicates': []
    }
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'shared_criterion',
        'client_id': 656565465,
        'is_negative': True,
        'criterion_type': 'Keyword',
        'match_type': 'EXACT',
        'keyword_text': 'Teste2',
        'shared_set_id': 5465465464
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'xsi_type': 'SharedCriterionOperation',
        'operand': {
            'criterion': {
                'text': 'Teste2',
                'xsi_type': 'Keyword',
                'matchType': 'EXACT'
            },
            'xsi_type': 'SharedCriterion',
            'negative': True,
            'sharedSetId': 5465465464
        },
        'operator': 'ADD'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_managed_customer_operations():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'managed_customer',
        'fields': ['Name', 'CustomerId'],
        'predicates': [
            ('CustomerId', 'EQUALS', 35345353534),
        ]
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))

    expected_get_adwords_operation = {
        'xsi_type': 'Selector',
        'predicates': [
            {
                'operator': 'EQUALS',
                'xsi_type': 'Predicate',
                'field': 'CustomerId',
                'values': [35345353534]
            }
        ],
        'paging': {'startIndex': 0, 'xsi_type': 'Paging', 'numberResults': 10000},
        'fields': ['Name', 'CustomerId'],
        'ordering': []
    }
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

    mutate_internal_operation = {
        'object_type': 'managed_customer',
        'name': 'Customer Name',
        'currency_code': 'BRL',
        'date_time_zone': 'America/Sao_Paulo'
    }

    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'xsi_type': 'ManagedCustomerOperation',
        'operand': {
            'currencyCode': 'BRL',
            'name': 'Customer Name',
            'dateTimeZone': 'America/Sao_Paulo'
        },
        'operator': 'ADD'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_attach_label_operations():
    operation_builder = OperationsBuilder()
    mutate_internal_operation = {
        'object_type': 'attach_label',
        'client_id': 9973876376,
        'campaign_id': 1341876198,
        'label_id': 34324324
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operator': 'ADD',
        'operand': {
            'labelId': 34324324,
            'campaignId': 1341876198
        },
        'xsi_type': 'CampaignLabelOperation'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

    mutate_internal_operation = {
        'object_type': 'attach_label',
        'client_id': 9973876376,
        'ad_id': 3453454353,
        'label_id': 34324324
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operator': 'ADD',
        'operand': {
            'labelId': 34324324,
            'adId': 3453454353
        },
        'xsi_type': 'AdGroupAdLabelOperation'
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

    mutate_internal_operation = {
        'object_type': 'attach_label',
        'client_id': 9973876376,
        'ad_group_id': 3453454353,
        'label_id': 34324324
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operator': 'ADD',
        'xsi_type': 'AdGroupLabelOperation',
        'operand': {
            'adGroupId': 3453454353,
            'labelId': 34324324}
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

    mutate_internal_operation = {
        'object_type': 'attach_label',
        'client_id': 9973876376,
        'customer_id': 3453454353,
        'label_id': 34324324
    }
    mutate_adwords_operation = next(operation_builder(mutate_internal_operation, sync=True))
    expected_mutate_adwords_operation = {
        'operator': 'ADD', 'operand': {
            'labelId': 34324324,
            'customerId': 3453454353
        }
    }
    assert expected_mutate_adwords_operation == mutate_adwords_operation

def _build_offline_conversions_operations():
    operation_builder = OperationsBuilder()
    client_id = 1234567890
    gclid = 'gclid_teste'
    conversion_name = 'conversion name'
    conversion_time = datetime(2018, 12, 30, 23, 59, 59)
    adjustment_time = datetime(2019, 12, 30, 23, 59, 59)
    conversion_value = 12.0
    conversion_currency_code = 'BRL'

    add_internal_operation = {
        'object_type': 'offline_conversion',
        'client_id': client_id,
        'google_click_id': gclid,
        'conversion_name': conversion_name,
        'conversion_time': conversion_time.isoformat(),
        'time_zone': 'America/Sao_Paulo',
        'conversion_value': conversion_value,
        'conversion_currency_code': conversion_currency_code,
    }

    set_internal_operation = {
        'object_type': 'offline_conversion',
        'client_id': client_id,
        'google_click_id': gclid,
        'conversion_name': conversion_name,
        'conversion_time': conversion_time.isoformat(),
        'adjustment_time': adjustment_time.isoformat(),
        'time_zone': 'America/Sao_Paulo',
        'conversion_value': conversion_value,
        'conversion_currency_code': conversion_currency_code,
        'operator': 'SET'
    }

    remove_internal_operation = {
        'object_type': 'offline_conversion',
        'client_id': client_id,
        'google_click_id': gclid,
        'conversion_name': conversion_name,
        'conversion_time': conversion_time.isoformat(),
        'adjustment_time': adjustment_time.isoformat(),
        'time_zone': 'America/Sao_Paulo',
        'conversion_value': conversion_value,
        'conversion_currency_code': conversion_currency_code,
        'operator': 'REMOVE'
    }

    add_adwords_operation = next(operation_builder(add_internal_operation, sync=True))

    expected_add_adwords_operation = {
        'xsi_type': 'OfflineConversionFeedOperation',
        'operand': {
            'xsi_type': 'OfflineConversionFeed',
            'googleClickId': 'gclid_teste',
            'conversionName': 'conversion name',
            'conversionTime': '20181230 235959 America/Sao_Paulo',
            'conversionValue': 12.0,
            'conversionCurrencyCode': 'BRL'
        },
        'operator': 'ADD'
    }
    assert add_adwords_operation == expected_add_adwords_operation

    set_adwords_operation = next(operation_builder(set_internal_operation, sync=True))
    expected_set_adwords_operation = {
        'xsi_type': 'OfflineConversionAdjustmentFeedOperation',
        'operand':
            {'xsi_type': 'GclidOfflineConversionAdjustmentFeed',
             'googleClickId': 'gclid_teste',
             'conversionName': 'conversion name',
             'conversionTime': '20181230 235959 America/Sao_Paulo',
             'adjustedValue': 12.0,
             'adjustedValueCurrencyCode': 'BRL',
             'adjustmentTime': '20191230 235959 America/Sao_Paulo',
             'adjustmentType': 'RESTATE'
             },
        'operator': 'ADD'
    }

    assert set_adwords_operation == expected_set_adwords_operation

    remove_adwords_operation = next(operation_builder(remove_internal_operation, sync=True))

    expected_remove_adwords_operation = {
        'xsi_type': 'OfflineConversionAdjustmentFeedOperation',
        'operand': {'xsi_type': 'GclidOfflineConversionAdjustmentFeed',
                    'googleClickId': 'gclid_teste',
                    'conversionName': 'conversion name',
                    'conversionTime': '20181230 235959 America/Sao_Paulo',
                    'adjustedValue': 12.0,
                    'adjustedValueCurrencyCode': 'BRL',
                    'adjustmentTime': '20191230 235959 America/Sao_Paulo',
                    'adjustmentType': 'RETRACT'
                    },
        'operator': 'ADD'
    }

    assert remove_adwords_operation == expected_remove_adwords_operation

def _build_operations_with_default_fields():
    operation_builder = OperationsBuilder()
    get_internal_operation = {
        'object_type': 'campaign_ad_schedule',
        'client_id': 7857288943,
        'default_fields': True
    }
    get_adwords_operation = next(operation_builder(get_internal_operation, sync=True))
    get_adwords_operation['fields'] = set(get_adwords_operation['fields'])
    expected_get_adwords_operation = {
        'paging': {
            'startIndex': 0,
            'xsi_type': 'Paging',
            'numberResults': 10000
        },
        'xsi_type': 'Selector',
        'fields': ['StartHour', 'StartMinute', 'BidModifier', 'EndHour', 'DayOfWeek', 'EndMinute'],
        'ordering': [],
        'predicates': [{
            'values': ['AD_SCHEDULE'],
            'xsi_type': 'Predicate',
            'operator': 'EQUALS',
            'field': 'CriteriaType'
        }]
    }
    get_adwords_operation['fields'] = sorted(get_adwords_operation['fields'])
    expected_get_adwords_operation['fields'] = sorted(expected_get_adwords_operation['fields'])
    assert expected_get_adwords_operation == get_adwords_operation

def _build_user_list_operation():
    operation_builder = OperationsBuilder()
    client_id = 1234567890
    name = 'Test UserList 9'

    add_list_internal_operation = {
        'object_type': 'user_list',
        'client_id': client_id,
        'name': name,
    }

    user_list_id = 123
    members = [
        {'email': 'user1@gmail.com', 'phone_number': '1234567898', 'mobile_id': 123},
        {'email': 'user2@gmail.com', 'phone_number': '1234562898', 'first_name': 'First Name', 'last_name': 'Last Name', 'country_code': 'BR', 'zip_code': 123},
        {'email': 'user3@gmail.com', 'phone_number': '1234562898', 'first_name': 'First Name', 'last_name': 'Last Name',
         'country_code': 'BR'}
    ]

    add_members_internal_operation = {
        'object_type': 'user_list_member',
        'client_id': client_id,
        'user_list_id': user_list_id,
        'members': members,
    }

    add_list_adwords_operation = next(operation_builder(add_list_internal_operation, sync=True))
    expected_add_list_adwords_operation = {
        'xsi_type': 'UserListOperation',
        'operator': 'ADD',
        'operand': {
            'xsi_type': 'CrmBasedUserList',
            'status': 'OPEN',
            'isEligibleForSearch': True,
            'isEligibleForDisplay': True,
            'membershipLifeSpan': 10000,
            'name': 'Test UserList 9',
            'uploadKeyType': 'CONTACT_INFO',
            'dataSourceType': 'FIRST_PARTY'
        }
    }
    assert add_list_adwords_operation == expected_add_list_adwords_operation

    add_list_members_adwords_operation = next(operation_builder(add_members_internal_operation, sync=True))

    expected_add_members_adwords_operation = {
        'xsi_type': 'MutateMembersOperation',
        'operator': 'ADD',
        'operand': {
            'xsi_type': 'MutateMembersOperand',
            'userListId': add_members_internal_operation['user_list_id'],
            'removeAll': False,
            'membersList': [{
                'hashedEmail': hashlib.sha256(add_members_internal_operation['members'][0]['email'].strip().lower().encode()).hexdigest(),
                'mobileId': add_members_internal_operation['members'][0]['mobile_id'],
                'hashedPhoneNumber': hashlib.sha256(add_members_internal_operation['members'][0]['phone_number'].strip().lower().encode()).hexdigest()
            }, {
                'hashedEmail': hashlib.sha256(add_members_internal_operation['members'][1]['email'].strip().lower().encode()).hexdigest(),
                'hashedPhoneNumber': hashlib.sha256(add_members_internal_operation['members'][1]['phone_number'].strip().lower().encode()).hexdigest(),
                'addressInfo': {
                    'hashedFirstName': hashlib.sha256(add_members_internal_operation['members'][1]['first_name'].strip().lower().encode()).hexdigest(),
                    'hashedLastName': hashlib.sha256(add_members_internal_operation['members'][1]['last_name'].strip().lower().encode()).hexdigest(),
                    'countryCode': add_members_internal_operation['members'][1]['country_code'],
                    'zipCode': add_members_internal_operation['members'][1]['zip_code']
                }
            }, {
                'hashedEmail': hashlib.sha256(add_members_internal_operation['members'][2]['email'].strip().lower().encode()).hexdigest(),
                'hashedPhoneNumber': hashlib.sha256(add_members_internal_operation['members'][2]['phone_number'].strip().lower().encode()).hexdigest()
            }]}
    }

    assert add_list_members_adwords_operation == expected_add_members_adwords_operation

def test_build_adwords_operations():
    _build_shared_set_operations()
    _build_budget_order_operations()
    _build_site_link_operations()
    _build_structured_snipppet_operations()
    _build_callout_operations()
    _build_campaign_ad_schedule_operations()
    _build_get_campaign_criterion_operations()
    _build_shared_set_operations()
    _build_campaign_shared_set_operations()
    _build_shared_criterion_operations()
    _build_managed_customer_operations()
    _build_attach_label_operations()
    _build_operations_with_default_fields()
    _build_campaign_ad_schedule_operations()
    _build_offline_conversions_operations()
    _build_user_list_operation()

def _assert_jobs(jobs):
    assert not jobs['dirty']
    assert not jobs['pending']
    for acc in jobs['done'].values():
        for job in acc.values():
            assert job['status'] == 'DONE'
            assert job['estimated_percent_executed'] == 100
            assert job['num_operations_executed'] == job['num_operations_succeeded'] == job['num_results_written']

def test_client():
    _assert_jobs(_delete_campaigns())
    _assert_jobs(_create_campaign())
    _assert_jobs(_adjust_bids())
    kw_report = _get_keywords_report()
    assert kw_report[0]['CpcBid'] == 4.20
    adg_report = _get_adgroups_report()
    assert adg_report[0]['CpcBid'] == 4.20
    _assert_jobs(_delete_campaigns())

def test_sync_operations():
    _sync_operations()

def test_get_accounts():
    client = AdWords()
    client.get_accounts()

def test_batchjobs():
    client = AdWords()
    list(client.get_batchjobs())


text:
SYNONYM

#### According to
Index Fungorum

#### Published in
null

#### Original name
Trichosporon lodderae Phaff, Mrak & O.B. Williams, 1952

### Remarks
null


text:
module.exports = pack

var npm = require("./npm.js")
  , install = require("./install.js")
  , cache = require("./cache.js")
  , fs = require("graceful-fs")
  , chain = require("slide").chain
  , path = require("path")
  , cwd = process.cwd()
  , writeStream = require('fs-write-stream-atomic')

pack.usage = "npm pack <pkg>"

// if it can be installed, it can be packed.
pack.completion = install.completion

function pack (args, silent, cb) {
  if (typeof cb !== "function") cb = silent, silent = false

  if (args.length === 0) args = ["."]

  chain(args.map(function (arg) { return function (cb) {
    pack_(arg, cb)
  }}), function (er, files) {
    if (er || silent) return cb(er, files)
    printFiles(files, cb)
  })
}

function printFiles (files, cb) {
  files = files.map(function (file) {
    return path.relative(cwd, file)
  })
  console.log(files.join("\n"))
  cb()
}

// add to cache, then cp to the cwd
function pack_ (pkg, cb) {
  cache.add(pkg, null, null, false, function (er, data) {
    if (er) return cb(er)

    var name = data.name
    // scoped packages get special treatment
    if (name[0] === "@") name = name.substr(1).replace(/\//g, "-")

    var fname = name + "-" + data.version + ".tgz"
      , cached = path.resolve( npm.cache
                             , data.name
                             , data.version
                             , "package.tgz" )
      , from = fs.createReadStream(cached)
      , to = writeStream(fname)
      , errState = null

    from.on("error", cb_)
    to.on("error", cb_)
    to.on("close", cb_)
    from.pipe(to)

    function cb_ (er) {
      if (errState) return
      if (er) return cb(errState = er)
      cb(null, fname)
    }
  })
}


text:
package org.adridadou.ethereum.propeller.converters.e2e

import java.math.BigInteger

import org.scalacheck.Arbitrary._
import org.scalacheck.Prop._
import org.scalatest.check.Checkers
import org.scalatest.{FlatSpec, Matchers}

/**
  * Created by davidroon on 26.03.18.
  * This code is released under Apache 2 license
  */
class ListTest extends FlatSpec with Matchers with Checkers with SolidityConversionHelper {

  "List type" should "be converted from and to the same value" in {
    val contract = contractObject[ListContract]
    check(forAll(arbitrary[Array[Int]])(checkEncode(contract, _)))
  }

  private def checkEncode(contractObject: ListContract, value: Array[Int]) = {
    val realValue = value.map(i => BigInt(i).abs.bigInteger)
    contractObject.lstFunc(realValue) shouldEqual realValue
    true
  }
}

trait ListContract {
  def lstFunc(value: Array[BigInteger]): Array[BigInteger]
}