001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2016 ForgeRock AS.
015 */
016
017package org.forgerock.api.models;
018
019import static org.forgerock.api.enums.CreateMode.*;
020
021import java.util.Arrays;
022import java.util.List;
023import java.util.Objects;
024
025import com.fasterxml.jackson.annotation.JsonProperty;
026import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
027import org.forgerock.api.ApiValidationException;
028import org.forgerock.api.enums.CreateMode;
029
030/**
031 * Class that represents the Create Operation type in API descriptor.
032 */
033@JsonDeserialize(builder = Create.Builder.class)
034public final class Create extends Operation {
035
036    private final CreateMode mode;
037    private final Boolean singleton;
038
039    /**
040     * Protected contstructor of the Create.
041     *
042     * @param builder Operation Builder
043     */
044    private Create(Builder builder) {
045        super(builder);
046        this.mode = builder.mode;
047        this.singleton = builder.singleton;
048
049        if (mode == null) {
050            throw new ApiValidationException("mode required");
051        }
052    }
053
054    /**
055     * Getter of the mode.
056     *
057     * @return Mode
058     */
059    public CreateMode getMode() {
060        return mode;
061    }
062
063    /**
064     * Informs if operation creates singleton resources.
065     *
066     * @return {@code true} if operation creates singleton resources and {@code false} otherwise
067     */
068    public Boolean isSingleton() {
069        return singleton;
070    }
071
072    /**
073     * Creates a new builder for Create.
074     *
075     * @return New builder instance
076     */
077    public static final Builder create() {
078        return new Builder();
079    }
080
081    /**
082     * Allocates the Create operation type to the given Resource Builder.
083     *
084     * @param resourceBuilder - Resource Builder to add the operation
085     */
086    @Override
087    protected void allocateToResource(Resource.Builder resourceBuilder) {
088        resourceBuilder.create(this);
089    }
090
091    /**
092     * Builds a Create object from the data in the annotation.
093     *
094     * @param create Create annotation that holds the data
095     * @param instanceOperations True if the resource is performing instance operations.
096     * @param descriptor The root descriptor to add definitions to.
097     * @param relativeType The type relative to which schema resources should be resolved.
098     * @return Create instance
099     */
100    public static Create fromAnnotation(org.forgerock.api.annotations.Create create, boolean instanceOperations,
101            ApiDescription descriptor, Class<?> relativeType) {
102        List<CreateMode> modes = Arrays.asList(create.modes());
103        if ((instanceOperations && !modes.contains(ID_FROM_CLIENT))
104                || (!instanceOperations && !modes.contains(ID_FROM_SERVER))) {
105            return null;
106        }
107        return create()
108                .detailsFromAnnotation(create.operationDescription(), descriptor, relativeType)
109                .mode(instanceOperations ? ID_FROM_CLIENT : ID_FROM_SERVER)
110                .build();
111    }
112
113    @Override
114    public boolean equals(Object o) {
115        if (this == o) {
116            return true;
117        }
118        if (o == null || getClass() != o.getClass()) {
119            return false;
120        }
121        if (!super.equals(o)) {
122            return false;
123        }
124        Create create = (Create) o;
125        return mode == create.mode
126                && Objects.equals(singleton, create.singleton);
127    }
128
129    @Override
130    public int hashCode() {
131        return Objects.hash(super.hashCode(), mode, singleton);
132    }
133
134    /**
135     * Builder for the Create.
136     */
137    public static final class Builder extends Operation.Builder<Builder> {
138
139        private CreateMode mode;
140        private Boolean singleton = false;
141
142        private Builder() {
143            super();
144        }
145
146
147        /**
148         * Setter for create-mode.
149         *
150         * @param mode Create-mode
151         * @return Builder
152         */
153        @JsonProperty("mode")
154        public Builder mode(CreateMode mode) {
155            this.mode = mode;
156            return this;
157        }
158
159        /**
160         * Setter for singleton.
161         *
162         * @param singleton Specifies that create operates on a singleton as opposed to a collection.
163         * @return Builder
164         */
165        @JsonProperty("singleton")
166        public Builder singleton(Boolean singleton) {
167            this.singleton = singleton;
168            return this;
169        }
170
171        /**
172         * Returns the builder so this.
173         *
174         * @return this
175         */
176        @Override
177        protected Builder self() {
178            return this;
179        }
180
181        /**
182         * Builds the Create instance.
183         *
184         * @return Create instance
185         */
186        public Create build() {
187            return new Create(this);
188        }
189    }
190
191}