View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2016 ForgeRock AS.
15   */
16  package org.forgerock.api.jackson;
17  
18  import static org.forgerock.api.jackson.JacksonUtils.validateEnum;
19  import static org.forgerock.api.jackson.JacksonUtils.validateFormatForNumber;
20  import static org.forgerock.api.jackson.JacksonUtils.validateMaximumAndMinimum;
21  import static org.forgerock.api.util.ValidationUtil.isEmpty;
22  
23  import com.fasterxml.jackson.annotation.JsonProperty;
24  import com.fasterxml.jackson.module.jsonSchema.jakarta.types.NumberSchema;
25  import jakarta.validation.ValidationException;
26  import java.math.BigDecimal;
27  import java.util.Collections;
28  import java.util.List;
29  import java.util.Map;
30  import org.forgerock.api.enums.ReadPolicy;
31  import org.forgerock.api.enums.WritePolicy;
32  import org.forgerock.json.JsonValue;
33  
34  /**
35   * An extension to the Jackson {@code NumberSchema} that includes the custom CREST JSON Schema attributes.
36   */
37  class CrestNumberSchema extends NumberSchema implements CrestReadWritePoliciesSchema, OrderedFieldSchema, EnumSchema,
38          ValidatableSchema, MultipleOfSchema, PropertyFormatSchema, MinimumMaximumSchema, WithExampleSchema<BigDecimal> {
39      private WritePolicy writePolicy;
40      private ReadPolicy readPolicy;
41      private Boolean errorOnWritePolicyFailure;
42      private Boolean returnOnDemand;
43      private Integer propertyOrder;
44      private Double multipleOf;
45      private String propertyFormat;
46      private BigDecimal propertyMinimum;
47      private BigDecimal propertyMaximum;
48      @JsonProperty
49      private Map<String, List<String>> options;
50      private BigDecimal example;
51  
52      @Override
53      public WritePolicy getWritePolicy() {
54          return writePolicy;
55      }
56  
57      @Override
58      public void setWritePolicy(WritePolicy policy) {
59          this.writePolicy = policy;
60      }
61  
62      @Override
63      public ReadPolicy getReadPolicy() {
64          return readPolicy;
65      }
66  
67      @Override
68      public void setReadPolicy(ReadPolicy readPolicy) {
69          this.readPolicy = readPolicy;
70      }
71  
72      @Override
73      public Boolean getErrorOnWritePolicyFailure() {
74          return errorOnWritePolicyFailure;
75      }
76  
77      @Override
78      public void setErrorOnWritePolicyFailure(Boolean errorOnWritePolicyFailure) {
79          this.errorOnWritePolicyFailure = errorOnWritePolicyFailure;
80      }
81  
82      @Override
83      public Boolean getReturnOnDemand() {
84          return returnOnDemand;
85      }
86  
87      @Override
88      public void setReturnOnDemand(Boolean returnOnDemand) {
89          this.returnOnDemand = returnOnDemand;
90      }
91  
92      @Override
93      public Integer getPropertyOrder() {
94          return propertyOrder;
95      }
96  
97      @Override
98      public void setPropertyOrder(Integer order) {
99          this.propertyOrder = order;
100     }
101 
102     @Override
103     public List<String> getEnumTitles() {
104         return options == null ? null : options.get(ENUM_TITLES);
105     }
106 
107     @Override
108     public void setEnumTitles(List<String> titles) {
109         this.options = Collections.singletonMap(ENUM_TITLES, titles);
110     }
111 
112     @Override
113     public void validate(JsonValue object) throws ValidationException {
114         if (!object.isNumber()) {
115             throw new ValidationException("Expected number, but got " + object.getObject());
116         }
117         Number number = object.asNumber();
118         validateMaximumAndMinimum(number, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum());
119         validateFormatForNumber(format);
120         validateEnum(enums, number.toString());
121     }
122 
123     @Override
124     public Double getMultipleOf() {
125         return multipleOf;
126     }
127 
128     @Override
129     public void setMultipleOf(Double multipleOf) {
130         this.multipleOf = multipleOf;
131     }
132 
133     /**
134      * Gets read-only property. This method overrides the superclass' definition of "readOnly" being all lower-case,
135      * via the {@code JsonProperty} annotation.
136      *
137      * @return {@code true} if property is read-only, otherwise {@code false} or {@code null}
138      */
139     @JsonProperty("readOnly")
140     @Override
141     public Boolean getReadonly() {
142         return super.getReadonly();
143     }
144 
145     // This method overrides the superclass' definition of "format" via JsonProperty annotation
146     @JsonProperty("format")
147     @Override
148     public String getPropertyFormat() {
149         if (!isEmpty(propertyFormat)) {
150             return propertyFormat;
151         }
152         // fallback to old behavior
153         return format == null ? null : format.toString();
154     }
155 
156     @Override
157     public void setPropertyFormat(String propertyFormat) {
158         this.propertyFormat = propertyFormat;
159     }
160 
161     // This method overrides the superclass' definition of "minimum" via JsonProperty annotation
162     @JsonProperty("minimum")
163     @Override
164     public BigDecimal getPropertyMinimum() {
165         return propertyMinimum;
166     }
167 
168     @Override
169     public void setPropertyMinimum(BigDecimal propertyMinimum) {
170         this.propertyMinimum = propertyMinimum;
171     }
172 
173     // This method overrides the superclass' definition of "maximum" via JsonProperty annotation
174     @JsonProperty("maximum")
175     @Override
176     public BigDecimal getPropertyMaximum() {
177         return propertyMaximum;
178     }
179 
180     @Override
181     public void setPropertyMaximum(BigDecimal propertyMaximum) {
182         this.propertyMaximum = propertyMaximum;
183     }
184 
185     @Override
186     public BigDecimal getExample() {
187         return example;
188     }
189 
190     @Override
191     public void setExample(String example) {
192         this.example = new BigDecimal(example);
193     }
194 }