001/*
002 * ============================================================================
003 *  Copyright © 2002-2023 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.config.spi.prefs;
019
020import static org.apiguardian.api.API.Status.STABLE;
021import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
022import static org.tquadrat.foundation.util.StringUtils.isNotEmpty;
023
024import java.util.prefs.BackingStoreException;
025import java.util.prefs.Preferences;
026
027import org.apiguardian.api.API;
028import org.tquadrat.foundation.annotation.ClassVersion;
029import org.tquadrat.foundation.config.spi.InvalidPreferenceValueException;
030import org.tquadrat.foundation.function.Getter;
031import org.tquadrat.foundation.function.Setter;
032import org.tquadrat.foundation.lang.StringConverter;
033
034/**
035 *  The abstract base class for custom implementations of
036 *  {@link PreferenceAccessor}.
037 *
038 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
039 *  @version $Id: PreferenceAccessorBase.java 1061 2023-09-25 16:32:43Z tquadrat $
040 *  @since 0.0.1
041 *
042 *  @param  <T> The type of the property.
043 *
044 *  @UMLGraph.link
045 */
046@ClassVersion( sourceVersion = "$Id: PreferenceAccessorBase.java 1061 2023-09-25 16:32:43Z tquadrat $" )
047@API( status = STABLE, since = "0.0.1" )
048public abstract class PreferenceAccessorBase<T> extends PreferenceAccessor<T>
049{
050        /*--------------*\
051    ====** Constructors **=====================================================
052        \*--------------*/
053    /**
054     *  Creates a new {@code PreferenceAccessorBase} instance.
055     *
056     *  @param  propertyName    The name of the property.
057     *  @param  getter  The property getter.
058     *  @param  setter  The property setter.
059     */
060    protected PreferenceAccessorBase( final String propertyName, final Getter<T> getter, final Setter<T> setter )
061    {
062        super( propertyName, getter, setter );
063    }   //  PreferenceAccessorBase()
064
065        /*---------*\
066    ====** Methods **==========================================================
067        \*---------*/
068    /**
069     *  <p>{@summary Converts the given String to an instance of the property
070     *  type.}</p>
071     *  <p>This implementation uses
072     *  {@link StringConverter#fromString(CharSequence)}
073     *  for the conversion.</p>
074     *
075     *  @param  node The &quot;preferences&quot; node that provides the value.
076     *  @param  s   The String value; can be {@code null}.
077     *  @return The propertyType instance; will be {@code null} if the provided
078     *      String is {@code null} or cannot be converted to the property type.
079     *  @throws InvalidPreferenceValueException The preferences value cannot be
080     *      translated to the property type.
081     */
082    protected abstract T fromString( final Preferences node, final String s ) throws InvalidPreferenceValueException;
083
084    /**
085     *  {@inheritDoc}
086     */
087    @Override
088    public void readPreference( final Preferences node ) throws BackingStoreException, InvalidPreferenceValueException
089    {
090        final var value = fromString( requireNonNullArgument( node, "node" ), node.get( getPropertyName(), toString( getter().get() ) ) );
091        setter().set( value );
092    }   //  readReference()
093
094    /**
095     *  <p>{@summary Converts the given instance of the property type to a
096     *  String.}</p>
097     *  <p>This implementation uses
098     *  {@link StringConverter#toString(Object)}
099     *  for the conversion.</p>
100     *
101     *  @param  t   The property value; can be {@code null}.
102     *  @return The String implementation; will be {@code null} if the provided
103     *      value is {@code null} or cannot be converted to a String.
104     */
105    protected abstract String toString( final T t );
106
107    /**
108     *  {@inheritDoc}
109     */
110    @Override
111    public void writePreference( final Preferences node ) throws BackingStoreException
112    {
113        requireNonNullArgument( node, "node" );
114        final var value = toString( getter().get() );
115        if( isNotEmpty( value ) )
116        {
117            node.put( getPropertyName(), value );
118        }
119        else
120        {
121            node.remove( getPropertyName() );
122        }
123    }   //  writePreference()
124}
125//  class PreferenceAccessorBase
126
127/*
128 *  End of File
129 */