/* Copyright (c) 2008 Google Inc. * * 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.google.gdata.model; import com.google.gdata.model.ElementMetadata.Cardinality; import com.google.gdata.model.ElementMetadata.SingleVirtualElement; import com.google.gdata.model.ElementMetadata.MultipleVirtualElement; import com.google.gdata.model.Metadata.VirtualValue; /** * An element creator allows setting element information, which includes the * following pieces: * <ul> * <li>name: The qualified name to use for input and output. Defaults to using * the value in the {@link ElementKey} associated with the metadata. Setting the * name here will override the default.</li> * <li>required: Validates that the element exists in both input and output. * Defaults to false.</li> * <li>visible: Hides or shows an element in the output. Defaults to true.</li> * <li>cardinality: Allows setting this element to allow a single or multiple * elements. See {@link Cardinality} for the valid values. Defaults to * {@link Cardinality#SINGLE}.</li> * <li>contentRequired: Sets the text content for this element to required. * Defaults to true if the {@link ElementKey} has a datatype other than * {@link Void}.</li> * <li>validator: Overrides the validator for this element. By default a * {@link MetadataValidator} is used.</li> * <li>properties: Additional properties used during parsing and generation. * Different wire formats support different properties. Defaults to * {@code null}.</li> * <li>valueTransform: Allows changing where the value of the element comes * from. By default the value comes from the text content field, but this can * be overridden by using a {@link VirtualValue}.</li> * <li>attributes: The ordered set of attributes expected for this element. * Defaults to empty. Adding an attribute can be accomplished by calling either * {@link #addAttribute} or {@link #replaceAttribute}, based on the desired * order in the output.</li> * <li>elements: The ordered set of child elements expected for this element. * Defaults to empty. Adding an element can be accomplished by calling either * {@link #addElement} or {@link #replaceElement}, * based on the desired order in the output.</li> * <li>adaptations: A map from adaptation key to adaptation. An adaptation * allows parsing into a generic base class and adapting the element into an * appropriate subclass based on key.</li> * </ul> * * */ public interface ElementCreator extends MetadataCreator { /** * Sets the name of the element. This can be used after copying some other * metadata to change the name. * * @param name the new name to use for the element. * @return this metadata creator for chaining. */ ElementCreator setName(QName name); /** * Sets the requiredness of this element. This means that the element * must appear in the parent element for the parent element to be valid. * * @param required true to set the element to required, false to set it * to optional (the default). * @return this metadata creator for chaining. */ ElementCreator setRequired(boolean required); /** * Sets whether this element is visible. If the element is not visible * then it will not be included in the output. This can be used to set the * state of an element to hidden if it is not part of the default set * of metadata. * * @param visible true to make the property visible (the default), false to * hide it from the output. * @return this metadata creator for chaining. */ ElementCreator setVisible(boolean visible); /** * Adds an adaptation from the element type of this element to the adaptation * type. An adaptation is a customization of a base type to a particular * variant type. Adaptations are used to allow adaptive parsing; the data is * first parsed into the base type and then adapted to a more specific variant * during resolution. If you are adding adaptations you should also override * {@link Element#narrow} and call * {@link Element#adapt(Element, ElementMetadata, String)} with the * appropriate key. */ ElementCreator adapt(String kind, ElementKey<?, ?> adaptation); /** * Sets the cardinality of the element. The cardinality can be either * {@link Cardinality#SINGLE} for only a single element, or * {@link Cardinality#MULTIPLE} for repeating elements. * * @param cardinality the cardinality of the element. * @return this element metadata builder for chaining. */ ElementCreator setCardinality(Cardinality cardinality); /** * Sets whether the element's content is required. By default the content is * required if the datatype is not {@link Void}. * * @param contentRequired true to set the content to required, false to set * it to optional. * @return this element metadata builder for chaining. */ ElementCreator setContentRequired(boolean contentRequired); /** * Sets the element's validator. The validator is used to check that the * element has all required attributes/elements/values. By default an * instance of {@link MetadataValidator} is used. * * @param validator element validator to use when validating the element, or * null if no validation is needed (for undeclared metadata). * @return this element metadata builder for chaining. */ ElementCreator setValidator(ElementValidator validator); /** * Sets the element's properties. This is used to provide additional * information during parsing/generation, and is specific to the wire format. * * @param properties default properties for the element. * @return this element metadata builder for chaining. */ ElementCreator setProperties(Object properties); /** * Sets the virtual text content of this element. This can change how the * text content of the element is rendered, but cannot be used for structural * changes to the element. For that use {@link #setSingleVirtualElement} * or {@link #setMultipleVirtualElement}. */ ElementCreator setVirtualValue(VirtualValue virtualValue); /** * Sets this metadata as representing a virtual element with single * cardinality. A virtual element is an element that only exists in the * metadata, and is used during parsing and generation to map to the base DOM. */ ElementCreator setSingleVirtualElement(SingleVirtualElement virtualElement); /** * Sets this metadata as representing a virtual element with multiple * cardinality. A virtual element is an element that only exists in the * metadata, and is used during parsing and generation to map to the base DOM. */ ElementCreator setMultipleVirtualElement( MultipleVirtualElement virtualElement); /** * Flattens this element. If the element has text content, this method will * cause its text content to be output as part of any parent element, rather * than as a separate nested element. Any attributes or child elements of * this element will not be generated on output, if you wish to output those * elements use the {@link #moveAttribute} and {@link #moveElement} methods to * place them somewhere else. */ ElementCreator flatten(); /** * Adds a new virtual attribute based on a path. The path is relative to this * element and must end in an attribute key. For example, if you want to add * the atom:title@type attribute to entry, you could do: * * <p>{@code * registry.build(Entry.KEY).addVirtual( * TextContent.TYPE, Path.of(Entry.TITLE, TextContent.TYPE)); * } * <p>Adding a virtual attribute will hide the source attribute in the output, * but any changes made to the source will also be applied to the virtual * location. * * @throws IllegalArgumentException if the path does not end in an attribute. */ AttributeCreator moveAttribute(AttributeKey<?> key, Path path); /** * Adds a new virtual element based on a path. The path is relative to this * element and must end in an element key. For example, if you want to add the * media:keywords element to media:group, you could do: * * <p>{@code * registry.build(Entry.KEY).addVirtual( * MediaKeyword.KEY, Path.of(MediaGroup.KEY, MediaKeyword.KEY)); * } * <p>Adding a virtual element will hide the source element in the output, but * any changes made to the source will also be applied to the virtual * location. * * @throws IllegalArgumentException if the path does not end in an element. */ ElementCreator moveElement(ElementKey<?, ?> key, Path path); /** * Sets the location of the undeclared attributes. By default, undeclared * attributes appear after all declared attributes, this lets them appear * earlier in the list. */ ElementCreator addUndeclaredAttributeMarker(); /** * Add the key for an attribute. If an attribute with the same ID * already exists, the previous attribute will be removed, and the new * attribute will be added to the end of the list. If you want to replace the * existing element, use {@link #replaceAttribute(AttributeKey)}. * * @param key the key to the attribute that is being added. * @return an attribute builder that can be used to set the attribute fields. */ AttributeCreator addAttribute(AttributeKey<?> key); /** * Replaces the existing metadata for an attribute. * * @param key the key to the attribute that is being replaced. * @return an attribute builder that can be used to modify the attribute. */ AttributeCreator replaceAttribute(AttributeKey<?> key); /** * Sets a list of attributes as the only visible attributes for an element, * and also places them into the given order in the element. */ ElementCreator orderAndWhitelistAttributes(AttributeKey<?>... keys); /** * Whitelists a set of attributes for this element metadata. This will hide * all declared attributes on the metadata instance that will be created from * this builder. This will not change the current order. */ ElementCreator whitelistAttributes(AttributeKey<?>... keys); /** * Sets the location of the undeclared elements. By default, undeclared * elements appear after all declared elements, this lets them appear * earlier in the list. */ ElementCreator addUndeclaredElementMarker(); /** * Add the metadata for a child element. If an element with the same ID * already exists, the previous element will be removed, and the new element * will be added to the end of the list. If you want to replace the existing * element, use {@link #replaceElement(ElementKey)}. * * @param element the key we are adding or pushing to the end. * @return the builder for the child element. */ ElementCreator addElement(ElementKey<?, ?> element); /** * Replaces the existing metadata for a child element. * * @param key the key we are replacing. * @return this element metadata builder for chaining. * @throws IllegalArgumentException if the child metadata doesn't exist. */ ElementCreator replaceElement(ElementKey<?, ?> key); /** * Sets a list of elements as the only visible child elements for an element, * and also places them into the given order in the element. */ ElementCreator orderAndWhitelistElements(ElementKey<?, ?>... keys); /** * Whitelists a set of child elements for this element metadata. This will * hide all declared child elements on the metadata instance that will be * created from this builder. This will not change the current order. */ ElementCreator whitelistElements(ElementKey<?, ?>... keys); /** * Blacklist a set of keys, these keys will be explicitly hidden from view. */ ElementCreator blacklistElements(ElementKey<?, ?>... keys); }