/*
* Copyright (c) 2010-2016 Evolveum
*
* Licensed 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 com.evolveum.midpoint.prism;
import com.evolveum.midpoint.prism.xnode.RootXNode;
import com.evolveum.midpoint.util.exception.SchemaException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.List;
/**
* Parses a given input into prism or POJO objects.
*
* The interface is pretty straightforward; only two things are of interest:
* 1. how to determine the type of data to be retrieved,
* 2. how to determine the name of the item that is to be created (in case of prism items).
*
* For most cases, both can be determined from the input. E.g. if we are parsing a prism object that is rooted at the
* "user" XML element, it is clear that the type is c:UserType and the name is c:user. In other cases, the algorithms
* are the following:
*
* Data type determination: We collect all the available data, i.e.
* - explicit type specification in source data (xsi:type/@type),
* - itemDefinition provided by the caller,
* - item name in source data,
* - itemName provided by the caller,
* - typeName provided by the caller,
* - typeClass provided by the caller
* and take the most specific of these. In case of conflict we report an error.
*
* Data name determination: First name that is present takes precedence:
* 1. itemName
* 2. source data (if namespace is missing, it is filled from item definition)
* 3. name from itemDefinition
* 4. name from item definition derived from type name
* 5. name from item definition derived from type class
*
* General post-conditions: (For items as well as item values; and for all parsing methods.)
* - All recognizable definitions are set.
* - Prism context is set on all items and PCVs.
* - No unresolved raw values with known types are present.
*
* @author mederly
*/
public interface PrismParser {
/**
* For string inputs: sets the data language that the parser will try to parse; null means auto-detect.
* For other kinds of input (DOM and XNode) the language is fixed to XML or none, respectively.
*
* @param language The language
* @return Updated parser.
*/
@NotNull
PrismParser language(@Nullable String language);
/**
* Sets the language of the parser to be XML.
* @return Updated parser.
*/
@NotNull
PrismParser xml();
/**
* Sets the language of the parser to be JSON.
* @return Updated parser.
*/
@NotNull
PrismParser json();
/**
* Sets the language of the parser to be YAML.
* @return Updated parser.
*/
@NotNull
PrismParser yaml();
/**
* Provides a parsing context for the parser. The context contains e.g. selection of strict/compat
* mode of operation (set by client) or a list of warnings (maintained by the parser).
* @param context The parsing context.
* @return Updated parser.
*/
@NotNull
PrismParser context(@NotNull ParsingContext context);
/**
* Switches the parser into "strict" parsing mode.
* @return Updated parser.
*/
@NotNull
PrismParser strict();
/**
* Switches the parser into "compatibility" (or relaxed) parsing mode.
* TODO description here
* @return Updated parser.
*/
@NotNull
PrismParser compat();
/**
* Tells parser which definition to use when parsing item (or an item value). Optional.
* @param itemDefinition The definition
* @return Updated parser.
*/
@NotNull
PrismParser definition(ItemDefinition<?> itemDefinition);
/**
* Tells parser what data type to expect. Optional.
* @param typeName Data type to expect.
* @return Updated parser.
*/
@NotNull
PrismParser type(QName typeName);
/**
* Tells parser what data type to expect. Optional.
* @param typeClass Data type to expect.
* @return Updated parser.
*/
@NotNull
PrismParser type(Class<?> typeClass);
/**
* Tells parser what name to use for parsed item. Optional.
* @param itemName Item name to use.
* @return Updated parser.
*/
@NotNull
PrismParser name(QName itemName);
/**
* Parses the input as a prism object.
* @return The object.
*/
@NotNull
<O extends Objectable> PrismObject<O> parse() throws SchemaException, IOException;
/**
* Parses the input as a prism item. (Object, container, reference, value.)
* May return raw property values as part of the prism structure, if definitions are not known.
* @return The item.
*/
<IV extends PrismValue, ID extends ItemDefinition> Item<IV,ID> parseItem() throws SchemaException, IOException;
/**
* Parses the input as a prism value. (Container value, reference value, property value.)
* May return raw property values as part of the prism structure, if definitions are not known.
* @return The item.
*/
<IV extends PrismValue> IV parseItemValue() throws SchemaException, IOException;
/**
* Parses a real value - either property or container value.
* @param clazz Expected class of the data. May be null if unknown.
* @return Real value - POJO, Containerable, Objectable or Referencable.
*/
<T> T parseRealValue(@Nullable Class<T> clazz) throws IOException, SchemaException;
/**
* Parses a real value. The class is not supplied by the caller, so it has to be determined from the data source.
* @return Real value - POJO, Containerable, Objectable or Referencable.
*/
<T> T parseRealValue() throws IOException, SchemaException;
/**
* Parses a real value and stores it into JAXBElement, using item name derived in the usual way.
*/
<T> JAXBElement<T> parseRealValueToJaxbElement() throws IOException, SchemaException;
/**
* Parses the input into RootXNode. This is a bit unusual approach, skipping the unmarshalling phase altogether.
* But it is useful at some places.
* @return RootXNode corresponding to the input.
*/
RootXNode parseToXNode() throws IOException, SchemaException;
/**
* Parses either an item, or a real value. It depends on the type declaration or item name in the source data.
* 1) If explicit type is present, it is taken into account. If it corresponds to a prism item, the input is parsed
* as a prism item. Otherwise, it is parsed as a real value (containerable or simple POJO), if possible.
* 2) If there is no type, the item name is consulted. If it corresponds to a prism item, the input is parsed
* as a prism item. Otherwise, an exception is thrown.
*
* Pre-set parameters (itemDefinition, typeName, itemName) must NOT be present.
*
* Use with utmost care. If at all possible, avoid it.
*
* @return either prism item (Item) or a real value (Object)
*/
@Deprecated
Object parseItemOrRealValue() throws IOException, SchemaException;
// ============= other methods (convenience ones, deprecated ones etc) =============
/**
* Parses the input as a collection of prism objects.
* Currently supported only for XML. (For the time being, it is used only in tests.)
* @return A list of objects.
*/
@NotNull
List<PrismObject<? extends Objectable>> parseObjects() throws SchemaException, IOException;
// /**
// * Parses the input as a single value of a prism container.
// * @return Single-valued container.
// */
// @NotNull
// <C extends Containerable> PrismContainer<C> parseContainer() throws SchemaException, IOException;
// /**
// * Parses an atomic value - i.e. something that could present a property
// * value, if such a property would exist.
// */
// <T> T parseAtomicValue(QName typeName) throws IOException, SchemaException;
}