<commit_before>
/*
 * Copyright (C) 2011 <NAME>. All rights reserved.
 *
 * $Id$
 */

package org.dellroad.stuff.jibx;

import java.util.Map;

import org.dellroad.stuff.java.IdGenerator;
import org.jibx.extras.IdDefRefMapperBase;
import org.jibx.runtime.IMarshallable;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;

/**
 * JiBX Marshaller/Unmarshaller that assigns unique ID's to each object and
 * replaces duplicate appearances of the same object with an IDREF reference.
 *
 * <p>
 * This class allows for easy ID/IDREF handling for existing classes, with minimal
 * modifications to those classes and no custom (un)marshaller subclasses.
 *
 * <h3>JiBX Mapping</h3>
 *
 * <p>
 * Suppose you have a class {@code Person.java} with a single {@code name} property
 * and you want to add ID/IDREF support to it.
 *
 * <p>
 * First add the following two pseudo-bean property methods to the classes:
 *
 * <blockquote><pre>
 *  import org.dellroad.stuff.jibx.IdMapper;
 *
 *  public class Person {
 *
 *      private String name;
 *
 *      public String getName() {
 *          return this.name;
 *      }
 *      public void setName(String name) {
 *          this.name = name;
 *      }
 *
 *      <b>// JiBX methods
 *      private String getJiBXId() {
 *          return IdMapper.getId(this);
 *      }
 *      private void setJiBXId(String id) {
 *          // do nothing
 *      }</b>
 *  }
 * </pre></blockquote>
 * Note: if you subclass {@code Person.java} from a different sub-package, you may need
 * to change the access privileges of those methods from {@code private} to {@code protected}.
 * </p>
 *
 * <p>
 * Next, define a concrete mapping for {@code Person.java} and add the {@code id} attribute:
 * <blockquote><pre>
 *  &lt;mapping name="Person" class="com.example.Person"&gt;
 *      <b>&lt;value name="id" style="attribute" ident="def"
 *        get-method="getJiBXId" set-method="setJiBXId"/&gt;</b>
 *      &lt;value name="name" field="name"/&gt;
 *  &lt;/mapping&gt;
 * </pre></blockquote>
 * </p>
 *
 * <p>
 * Finally, use {@link IdMapper} as the custom marshaller and unmarshaller wherever a {@code Person} appears, e.g.:
 * <blockquote><pre>
 *  &lt;mapping name="Company" class="com.example.Company"&gt;
 *      &lt;collection name="Employees" field="employees" create-type="java.util.ArrayList"&gt;
 *          &lt;structure name="Person" type="com.example.Person"
 *            <b>marshaller="org.dellroad.stuff.jibx.IdMapper"
 *            unmarshaller="org.dellroad.stuff.jibx.IdMapper"</b>/&gt;
 *      &lt;/collection&gt;
 *      &lt;structure name="EmployeeOfTheWeek"&gt;
 *          &lt;structure name="Person" field="employeeOfTheWeek"
 *            <b>marshaller="org.dellroad.stuff.jibx.IdMapper"
 *            unmarshaller="org.dellroad.stuff.jibx.IdMapper"</b>/&gt;
 *      &lt;/structure&gt;
 *  &lt;/mapping&gt;
 * </pre></blockquote>
 * Note the {@code EmployeeOfTheWeek} "wrapper" element for the {@code employeeOfTheWeek} field; this is required
 * in order to use an XML name for this field other than {@code Person} (see limitations below).
 * </p>
 *
 * <p>
 * Now the first appearance of any {@code Person} will contain the full XML structure with an additional <code>id="..."</code>
 * attribute, while all subsequent appearances will contain just a reference of the form <code>&lt;Person idref="..."/&gt;</code>.
 * Conversely, when unmarshalled all {@code Person} XML elements that refer to the same original {@code Person} will
 * re-use the same unmarshalled {@code Person} object.
 * </p>
 *
 * <p>
 * So the resulting XML might look like:
 * <blockquote><pre>
 *  &lt;Company&gt;
 *      &lt;Employees&gt;
 *          &lt;Person id="N00001"&gt;
 *              &lt;name&gt;<NAME>&lt;/name&gt;
 *          &lt;/Person&gt;
 *          &lt;Person id="N00002"&gt;
 *              &lt;name&gt;<NAME>&lt;/name&gt;
 *          &lt;/Person&gt;
 *          ...
 *      &lt;/Employees&gt;
 *      &lt;EmployeeOfTheWeek&gt;
 *          &lt;Person idref="N00001"/&gt;
 *      &lt;/EmployeeOfTheWeek&gt;
 *  &lt;/Company&gt;
 * </pre></blockquote>
 * </p>
 *
 * <h3>Limitations</h3>
 *
 * <p>
 * JiBX and this class impose some limitations:
 * <ul>
 * <li>JiBX marshalling must be performed within an invocation of {@link IdGenerator#run IdGenerator.run()}
 *      so that an {@link IdGenerator} is available to generate the unique IDs (when using Spring, consider using
 *      {@link IdMappingMarshaller}; otherwise, the {@link JiBXUtil} methods all satisfy this requirement).</li>
 * <li>Classes that use ID/IDREF must have concrete JiBX mappings.</li>
 * <li>All occurences of the class must use the XML element name of the concrete mapping, so the use of
 *      a "wrapper" element is required when a different element name is desired.</li>
 * </ul>
 *
 * <h3>A Simpler Approach</h3>
 *
 * The above approach is useful when you don't want to keep track of which instance of an object will appear first
 * in the XML encoding: the first one will always fully define the object, while subsequent ones will just reference it.
 *
 * <p>
 * If this flexibility is not needed, i.e., if you can identify where in your mapping the first occurrence of an object
 * will appear, then the following simpler approach works without the above approach's limitations (other than requiring
 * that marshalling be peformed within an invocation of {@link IdGenerator#run IdGenerator.run()}):
 *
 * <p>
 * First, replace the <code>// do nothing</code> in the example above with call to {@link IdMapper#setId IdMapper.setId()},
 * and add a custom deserializer delegating to {@link ParseUtil#deserializeReference ParseUtil.deserializeReference()} to
 * <blockquote><pre>
 *      private void setJiBXId(String id) {
 *          IdMapper.setId(this, id);
 *      }
 *
 *      public static Employee deserializeEmployeeReference(String string) throws JiBXParseException {
 *          return ParseUtil.deserializeReference(string, Employee.class);
 *      }
 * </pre></blockquote>
 * </p>
 *
 * <p>
 * Then, map the first occurrence of an object exactly as in the concrete mapping above, exposing the <code>JiBXId</code> property.
 * In all subsequent occurrences of the object, expose the reference to the object as a simple property using the custom
 * serializer/deserializer pair {@link ParseUtil#serializeReference ParseUtil.serializeReference()} and
 * {@link ParseUtil#deserializeReference ParseUtil.deserializeReference()}.
 * </p>
 *
 * <p>
 * For example, the following binding would yeild the same XML encoding as before:
 * <blockquote><pre>
 *  &lt;mapping abstract="true" type-name="person" class="com.example.Person"&gt;
 *      <b>&lt;value name="id" style="attribute" ident="def"
 *        get-method="getJiBXId" set-method="setJiBXId"/&gt;</b>
 *      &lt;value name="name" field="name"/&gt;
 *  &lt;/mapping&gt;<commit_msg>Javadoc tweak.<commit_after>
/*
 * Copyright (C) 2011 <NAME>. All rights reserved.
 *
 * $Id$
 */

package org.dellroad.stuff.jibx;

import java.util.Map;

import org.dellroad.stuff.java.IdGenerator;
import org.jibx.extras.IdDefRefMapperBase;
import org.jibx.runtime.IMarshallable;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;

/**
 * JiBX Marshaller/Unmarshaller that assigns unique ID's to each object and
 * replaces duplicate appearances of the same object with an IDREF reference.
 *
 * <p>
 * This class allows for easy ID/IDREF handling for existing classes, with minimal
 * modifications to those classes and no custom (un)marshaller subclasses.
 *
 * <h3>JiBX Mapping</h3>
 *
 * <p>
 * Suppose you have a class {@code Person.java} with a single {@code name} property
 * and you want to add ID/IDREF support to it.
 *
 * <p>
 * First add the following two pseudo-bean property methods to the classes:
 *
 * <blockquote><pre>
 *  import org.dellroad.stuff.jibx.IdMapper;
 *
 *  public class Person {
 *
 *      private String name;
 *
 *      public String getName() {
 *          return this.name;
 *      }
 *      public void setName(String name) {
 *          this.name = name;
 *      }
 *
 *      <b>// JiBX methods
 *      private String getJiBXId() {
 *          return IdMapper.getId(this);
 *      }
 *      private void setJiBXId(String id) {
 *          // do nothing
 *      }</b>
 *  }
 * </pre></blockquote>
 * Note: if you subclass {@code Person.java} from a different sub-package, you may need
 * to change the access privileges of those methods from {@code private} to {@code protected}.
 * </p>
 *
 * <p>
 * Next, define a concrete mapping for {@code Person.java} and add the {@code id} attribute:
 * <blockquote><pre>
 *  &lt;mapping name="Person" class="com.example.Person"&gt;
 *      <b>&lt;value name="id" style="attribute" ident="def"
 *        get-method="getJiBXId" set-method="setJiBXId"/&gt;</b>
 *      &lt;value name="name" field="name"/&gt;
 *  &lt;/mapping&gt;
 * </pre></blockquote>
 * </p>
 *
 * <p>
 * Finally, use {@link IdMapper} as the custom marshaller and unmarshaller wherever a {@code Person} appears, e.g.:
 * <blockquote><pre>
 *  &lt;mapping name="Company" class="com.example.Company"&gt;
 *      &lt;collection name="Employees" field="employees" create-type="java.util.ArrayList"&gt;
 *          &lt;structure name="Person" type="com.example.Person"
 *            <b>marshaller="org.dellroad.stuff.jibx.IdMapper"
 *            unmarshaller="org.dellroad.stuff.jibx.IdMapper"</b>/&gt;
 *      &lt;/collection&gt;
 *      &lt;structure name="EmployeeOfTheWeek"&gt;
 *          &lt;structure name="Person" field="employeeOfTheWeek"
 *            <b>marshaller="org.dellroad.stuff.jibx.IdMapper"
 *            unmarshaller="org.dellroad.stuff.jibx.IdMapper"</b>/&gt;
 *      &lt;/structure&gt;
 *  &lt;/mapping&gt;
 * </pre></blockquote>
 * Note the {@code EmployeeOfTheWeek} "wrapper" element for the {@code employeeOfTheWeek} field; this is required
 * in order to use an XML name for this field other than {@code Person} (see limitations below).
 * </p>
 *
 * <p>
 * Now the first appearance of any {@code Person} will contain the full XML structure with an additional <code>id="..."</code>
 * attribute, while all subsequent appearances will contain just a reference of the form <code>&lt;Person idref="..."/&gt;</code>.
 * Conversely, when unmarshalled all {@code Person} XML elements that refer to the same original {@code Person} will
 * re-use the same unmarshalled {@code Person} object.
 * </p>
 *
 * <p>
 * So the resulting XML might look like:
 * <blockquote><pre>
 *  &lt;Company&gt;
 *      &lt;Employees&gt;
 *          &lt;Person id="N00001"&gt;
 *              &lt;name&gt;<NAME>&lt;/name&gt;
 *          &lt;/Person&gt;
 *          &lt;Person id="N00002"&gt;
 *              &lt;name&gt;<NAME>&lt;/name&gt;
 *          &lt;/Person&gt;
 *          ...
 *      &lt;/Employees&gt;
 *      &lt;EmployeeOfTheWeek&gt;
 *          &lt;Person idref="N00001"/&gt;
 *      &lt;/EmployeeOfTheWeek&gt;
 *  &lt;/Company&gt;
 * </pre></blockquote>
 * </p>
 *
 * <h3>Limitations</h3>
 *
 * <p>
 * JiBX and this class impose some limitations:
 * <ul>
 * <li>JiBX marshalling must be performed within an invocation of {@link IdGenerator#run IdGenerator.run()}
 *      so that an {@link IdGenerator} is available to generate the unique IDs (when using Spring, consider using
 *      {@link IdMappingMarshaller}; otherwise, the {@link JiBXUtil} methods all satisfy this requirement).</li>
 * <li>Classes that use ID/IDREF must have concrete JiBX mappings.</li>
 * <li>All occurences of the class must use the XML element name of the concrete mapping, so the use of
 *      a "wrapper" element is required when a different element name is desired.</li>
 * </ul>
 *
 * <h3>A Simpler Approach</h3>
 *
 * The above approach is useful when you don't want to keep track of which instance of an object will appear first
 * in the XML encoding: the first one will always fully define the object, while subsequent ones will just reference it.
 *
 * <p>
 * If this flexibility is not needed, i.e., if you can identify where in your mapping the first occurrence of an object
 * will appear, then the following simpler approach works without the above approach's limitations (other than requiring
 * that marshalling be peformed within an invocation of {@link IdGenerator#run IdGenerator.run()}):
 *
 * <p>
 * First, replace the <code>// do nothing</code> in the example above with call to {@link IdMapper#setId IdMapper.setId()},
 * and add a custom deserializer delegating to {@link ParseUtil#deserializeReference ParseUtil.deserializeReference()} to
 * <blockquote><pre>
 *      private void setJiBXId(String id) {
 *          IdMapper.setId(this, id);
 *      }
 *
 *      public static Employee deserializeEmployeeReference(String string) throws JiBXParseException {
 *          return ParseUtil.deserializeReference(string, Employee.class);
 *      }
 * </pre></blockquote>
 * </p>
 *
 * <p>
 * Then, map the first occurrence of an object exactly as in the concrete mapping above, exposing the <code>JiBXId</code> property.
 * In all subsequent occurrences of the object, expose the reference to the object as a simple property using the custom
 * serializer/deserializer pair {@link ParseUtil#serializeReference ParseUtil.serializeReference()} and
 * {@code Employee.deserializeEmployeeReference()}.
 * </p>
 *
 * <p>
 * For example, the following binding would yeild the same XML encoding as before:
 * <blockquote><pre>
 *  &lt;mapping abstract="true" type-name="person" class="com.example.Person"&gt;
 *      <b>&lt;value name="id" style="attribute" ident="def"
 *        get-method="getJiBXId" set-method="setJiBXId"/&gt;</b>
 *      &lt;value name="name" field="name"/&gt;
 *  &lt;/mapping&gt;
{'fraction_non_alphanumeric': 0.13311243967442196, 'fraction_numerical': 0.0036015270474681264, 'mean_word_length': 3.4932038834951458, 'pattern_counts': {'":': 0, '<': 155, '<?xml version=': 0, '>': 155, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3623190', 'n_tokens_mistral': 4393, 'n_tokens_neox': 4286, 'n_words': 1337}