001package com.identityworksllc.iiq.common;
002
003import sailpoint.api.SailPointContext;
004import sailpoint.object.QueryOptions;
005import sailpoint.object.Reference;
006import sailpoint.object.SailPointObject;
007import sailpoint.tools.GeneralException;
008
009import java.io.Serializable;
010import java.util.Arrays;
011import java.util.List;
012import java.util.Objects;
013import java.util.function.Function;
014
015/**
016 * Constructs IIQ {@link Reference} objects using a standardized API
017 */
018public final class Ref {
019    /**
020     * A constant that can be passed to context.search() to retrieve an object for use here
021     */
022    @SuppressWarnings("unused")
023    public static final List<String> REFERENCE_PROPS = Arrays.asList("id");
024
025    /**
026     * Retrieves a dehydrated object given the type and ID
027     * @param type The type of the object to create a reference to
028     * @param id The object ID
029     * @return A Reference to that object
030     */
031    public static Reference of(Class<? extends SailPointObject> type, String id) {
032        return new Reference(type.getName(), Objects.requireNonNull(id));
033    }
034
035    /**
036     * Retrieves a dehydrated object given the type and parameters
037     * @param type The type of the object to create a reference to
038     * @param parameters The result of a {@link SailPointContext#search(Class, QueryOptions, List)} call with the 'id' in the first position
039     * @return A Reference to that object
040     */
041    public static Reference of(Class<? extends SailPointObject> type, Object[] parameters) {
042        if (parameters == null || parameters.length < 1) {
043            throw new IllegalArgumentException("The parameters must contain at least an object ID");
044        }
045        if (parameters[0] instanceof String) {
046            return new Reference(type.getName(), (String)parameters[0]);
047        } else {
048            throw new IllegalArgumentException("The first item in the parameters must be a String object ID");
049        }
050    }
051
052    /**
053     * Retrieves a dehydrated reference from the object
054     * @param object The object to dehydrate
055     * @return The dehydrated reference
056     */
057    public static Reference of(SailPointObject object) {
058        return new Reference(Objects.requireNonNull(object));
059    }
060
061    /**
062     * Creates a type transforming function that will take any object that this class
063     * recognizes and convert it into a Reference of the appropriate type.
064     *
065     * This could be used, for example, as the second parameter passed to TransformingIterator's
066     * constructor.
067     *
068     * @param targetClass The target class to retrieve a reference for
069     * @param <T> The type of the target class
070     * @return a function converting the input to a reference
071     */
072    public static <T extends SailPointObject> Function<?, Reference> transformer(Class<T> targetClass) {
073        return o -> {
074            if (o instanceof String) {
075                return Ref.of(targetClass, (String)o);
076            } else if (o instanceof Object[]) {
077                return Ref.of(targetClass, (Object[])o);
078            } else if (o instanceof SailPointObject) {
079                return Ref.of((SailPointObject) o);
080            } else {
081                throw new IllegalArgumentException("Invalid input type: " + Utilities.safeClassName(o));
082            }
083        };
084    }
085
086    /**
087     * Private utility constructor
088     */
089    private Ref() {}
090
091
092}