001/*
002 * Portions of this software was developed by employees of the National Institute
003 * of Standards and Technology (NIST), an agency of the Federal Government and is
004 * being made available as a public service. Pursuant to title 17 United States
005 * Code Section 105, works of NIST employees are not subject to copyright
006 * protection in the United States. This software may be subject to foreign
007 * copyright. Permission in the United States and in foreign countries, to the
008 * extent that NIST may hold copyright, to use, copy, modify, create derivative
009 * works, and distribute this software and its documentation without fee is hereby
010 * granted on a non-exclusive basis, provided that this notice and disclaimer
011 * of warranty appears in all copies.
012 *
013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
025 */
026
027package gov.nist.secauto.metaschema.databind.model.info;
028
029import com.fasterxml.jackson.core.JsonToken;
030
031import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
032import gov.nist.secauto.metaschema.databind.io.BindingException;
033import gov.nist.secauto.metaschema.databind.io.json.IJsonParsingContext;
034import gov.nist.secauto.metaschema.databind.io.json.IJsonWritingContext;
035import gov.nist.secauto.metaschema.databind.io.xml.IXmlParsingContext;
036import gov.nist.secauto.metaschema.databind.io.xml.IXmlWritingContext;
037import gov.nist.secauto.metaschema.databind.model.IBoundFieldInstance;
038import gov.nist.secauto.metaschema.databind.model.IBoundNamedModelInstance;
039import gov.nist.secauto.metaschema.databind.model.IClassBinding;
040
041import java.io.IOException;
042
043import javax.xml.namespace.QName;
044import javax.xml.stream.XMLStreamException;
045import javax.xml.stream.events.StartElement;
046
047import edu.umd.cs.findbugs.annotations.NonNull;
048import edu.umd.cs.findbugs.annotations.Nullable;
049
050// TODO: get rid of functional interfaces
051public interface IDataTypeHandler {
052  @NonNull
053  static IDataTypeHandler newDataTypeHandler(
054      @NonNull IBoundNamedModelInstance targetInstance,
055      @NonNull IClassBinding classBinding) {
056    return new ClassDataTypeHandler(targetInstance, classBinding);
057  }
058
059  @NonNull
060  static IDataTypeHandler newDataTypeHandler(
061      @NonNull IClassBinding classBinding) {
062    return new ClassDataTypeHandler(null, classBinding);
063  }
064
065  @NonNull
066  static IDataTypeHandler newDataTypeHandler(
067      @NonNull IBoundFieldInstance property) {
068    return new JavaTypeAdapterDataTypeHandler(property);
069  }
070
071  /**
072   * Get the class binding associated with this handler.
073   *
074   * @return the class binding or {@code null} if the property's item type is not
075   *         a bound class
076   */
077  IClassBinding getClassBinding();
078
079  /**
080   * Get the associated {@link IDataTypeAdapter}, if the data type is not a
081   * complex bound object.
082   *
083   * @return the adpater, or {@code null} otherwise
084   */
085  IDataTypeAdapter<?> getJavaTypeAdapter();
086
087  /**
088   * Indicate if the value supported by this handler allows values without an XML
089   * element wrapper.
090   * <p>
091   * Implementations may proxy this request to the JavaTypeAdapter if it is used
092   * or return {@code false} otherwise.
093   *
094   * @return {@code true} if the underlying data type is allowed to be unwrapped,
095   *         or {@code false} otherwise
096   */
097  boolean isUnwrappedValueAllowedInXml();
098
099  boolean isJsonKeyRequired();
100
101  /**
102   * Parse and return the set of items from the JSON stream.
103   * <p>
104   * An item is a complete value, which can be a {@link JsonToken#START_OBJECT},
105   * or a value token.
106   *
107   * @param <T>
108   *          the Java type of the bound object described by this class
109   * @param parentObject
110   *          the parent Java object to use for serialization callbacks, or
111   *          {@code null} if there is no parent
112   * @param context
113   *          the JSON/YAML parser
114   * @return the Java object representing the set of parsed items
115   * @throws IOException
116   *           if an error occurred while parsing
117   */
118  @NonNull
119  <T> T readItem(
120      @Nullable Object parentObject,
121      @NonNull IJsonParsingContext context) throws IOException;
122
123  /**
124   * Parse and return the set of items from the XML stream.
125   *
126   * @param parentObject
127   *          the parent Java object to use for serialization callbacks
128   * @param parentName
129   *          the name of the parent (containing) element
130   * @param context
131   *          the XML writing context
132   * @return the Java object representing the set of parsed items
133   * @throws IOException
134   *           if an error occurred while writing
135   * @throws XMLStreamException
136   *           if an error occurred while generating the XML
137   */
138  @NonNull
139  Object readItem(
140      @NonNull Object parentObject,
141      @NonNull StartElement parentName,
142      @NonNull IXmlParsingContext context) throws IOException, XMLStreamException;
143
144  /**
145   * Write the provided {@code targetObject} as JSON.
146   *
147   * @param targetObject
148   *          the data to write
149   * @param context
150   *          the JSON writing context
151   * @throws IOException
152   *           if an error occurred while writing
153   */
154  void writeItem(
155      @NonNull Object targetObject,
156      @NonNull IJsonWritingContext context) throws IOException;
157
158  /**
159   * Write the provided value as XML.
160   *
161   * @param value
162   *          the item to write
163   * @param currentParentName
164   *          the name of the parent (containing) element
165   * @param context
166   *          the JSON serializer
167   * @throws IOException
168   *           if an error occurred while writing
169   * @throws XMLStreamException
170   *           if an error occurred while generating the XML
171   */
172  void writeItem(
173      @NonNull Object value,
174      @NonNull QName currentParentName,
175      @NonNull IXmlWritingContext context) throws IOException, XMLStreamException;
176
177  /**
178   * Build and return a deep copy of the provided item.
179   *
180   * @param item
181   *          the item to copy
182   * @param parentInstance
183   *          an optional parent object to use for serialization callbacks
184   * @return the new deep copy
185   * @throws BindingException
186   *           if an error occurred while analyzing the bound objects
187   */
188  @NonNull
189  Object copyItem(@NonNull Object item, @Nullable Object parentInstance) throws BindingException;
190
191}