package com.fasterxml.jackson.jr.ob.api;

import java.util.*;

import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.ob.JSON.Feature;
import com.fasterxml.jackson.jr.ob.impl.DeferredMap;
import com.fasterxml.jackson.jr.ob.JSONObjectException;

Helper class that is used for constructing Maps to map JSON Object values in.

Objects server both as "factories" for creating new builders (blueprint style), and as actual builders. For each distinct read operation, newBuilder will be called at least once; this instance may be used and reused multiple times, as calling start will reset the state so that more Lists may be built.

/** * Helper class that is used for constructing {@link java.util.Map}s * to map JSON Object values in. *<p> * Objects server both as "factories" for creating new builders (blueprint * style), and as actual builders. For each distinct read operation, * {@link #newBuilder} will be called at least once; this instance * may be used and reused multiple times, as calling {@link #start} * will reset the state so that more {@link List}s may be built. */
public abstract class MapBuilder { protected final int _features; protected final boolean _checkDups;
Optional Map implementation class, used when specific implementation is desired.
/** * Optional {@link Map} implementation class, used when specific * implementation is desired. */
protected final Class<?> _mapType; protected MapBuilder(int features, Class<?> type) { _features = features; _checkDups = JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS.isEnabled(features); _mapType = type; }
Factory method for getting a blueprint instance of the default MapBuilder implementation.
/** * Factory method for getting a blueprint instance of the default * {@link MapBuilder} implementation. */
public static MapBuilder defaultImpl() { return new Default(0, null); } public abstract MapBuilder newBuilder(int features); public abstract MapBuilder newBuilder(Class<?> mapImpl); public MapBuilder newBuilder() { return newBuilder(_features); } public final boolean isEnabled(JSON.Feature f) { return f.isEnabled(_features); } public abstract MapBuilder start(); public abstract MapBuilder put(String key, Object value); public abstract Map<String, Object> build();
Specialized method that is called when an empty list needs to be constructed; this may be a new list, or an immutable shared List, depending on implementation.

Default implementation simply calls:

 start().build();
which assumes that a builder has been constructed with newBuilder
/** * Specialized method that is called when an empty list needs to * be constructed; this may be a new list, or an immutable shared * List, depending on implementation. *<p> * Default implementation simply calls: *<pre> * start().build(); *</pre> * which assumes that a builder has been constructed with {@link #newBuilder} */
public Map<String, Object> emptyMap() throws JSONObjectException { return start().build(); }
Specialized method that is called when an empty list needs to be constructed; this may be a new list, or an immutable shared List, depending on implementation.

Default implementation simply calls:

 start().put(key, value).build();
/** * Specialized method that is called when an empty list needs to * be constructed; this may be a new list, or an immutable shared * List, depending on implementation. *<p> * Default implementation simply calls: *<pre> * start().put(key, value).build(); *</pre> */
public Map<String, Object> singletonMap(String key, Object value) throws JSONObjectException { return start().put(key, value).build(); } /* /********************************************************** /* Default implementation /********************************************************** */
Default MapBuilder implementation which builds either HashMap or LinkedHashMap instances (depending on Feature.PRESERVE_FIELD_ORDERING). It may also, with alternate configuration, use Collections.emptyMap() for empty Maps, if allowed with Feature.READ_ONLY.
/** * Default {@link MapBuilder} implementation which builds * either {@link HashMap} or {@link LinkedHashMap} instances * (depending on {@link Feature#PRESERVE_FIELD_ORDERING}). * It may also, with alternate configuration, * use {@link Collections#emptyMap()} for empty Maps, * if allowed with {@link Feature#READ_ONLY}. */
public static class Default extends MapBuilder { protected Map<String, Object> _current; protected Default(int features, Class<?> type) { super(features, type); } @Override public MapBuilder newBuilder(int features) { return new Default(features, _mapType); } @Override public MapBuilder newBuilder(Class<?> mapImpl) { return new Default(_features, mapImpl); } @Override public MapBuilder start() { // If this builder is "busy", create a new one... if (_current != null) { return newBuilder().start(); } _current = _map(12); return this; } @Override public Map<String, Object> build() { Map<String, Object> result = _current; _current = null; return result; } @Override public MapBuilder put(String key, Object value) { if (_checkDups) { if (_current.containsKey(key)) { // 14-Apr-2017, tatu: Note that choice of `IllegalArgumentException` is arbitrary // but not random: caller catches and re-packages it to give context throw new IllegalArgumentException("Duplicate key (key '"+key+"')"); } } _current.put(key, value); return this; } @Override public Map<String, Object> emptyMap() { if ((_mapType == null) && isEnabled(Feature.READ_ONLY)) { return Collections.emptyMap(); } return _map(4); } private final Map<String, Object> _map(int initialSize) { if (_mapType != null) { try { @SuppressWarnings("unchecked") Map<String,Object> m = (Map<String,Object>) _mapType.getDeclaredConstructor().newInstance(); return m; } catch (Exception e) { Throwable t = e; while (t.getCause() != null) { t = t.getCause(); } throw new IllegalArgumentException("Failed to create an instance of " +_mapType.getName()+" ("+t.getClass().getName()+"): "+t.getMessage()); } } final boolean sort = isEnabled(Feature.PRESERVE_FIELD_ORDERING); if (isEnabled(Feature.USE_DEFERRED_MAPS)) { return new DeferredMap(sort, initialSize); } return sort ? new LinkedHashMap<String, Object>(initialSize) : new HashMap<String, Object>(initialSize); } } }