com.ericsson.deviceaccess.spi.impl.genericdevice.GDPropertiesImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.ericsson.deviceaccess.spi.impl.genericdevice.GDPropertiesImpl.java

Source

/*
 * Copyright Ericsson AB 2011-2014. All Rights Reserved.
 *
 * The contents of this file are subject to the Lesser GNU Public License,
 *  (the "License"), either version 2.1 of the License, or
 * (at your option) any later version.; you may not use this file except in
 * compliance with the License. You should have received a copy of the
 * License along with this software. If not, it can be
 * retrieved online at https://www.gnu.org/licenses/lgpl.html. Moreover
 * it could also be requested from Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
 * WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
 * EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
 * OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND,
    
 * EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
 * LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
 * YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 *
 * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 * REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
 * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
 * DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
 * (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
 * INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE
 * OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
 * HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 */
package com.ericsson.deviceaccess.spi.impl.genericdevice;

import com.ericsson.common.util.serialization.Format;
import com.ericsson.common.util.serialization.SerializationException;
import com.ericsson.common.util.serialization.SerializationUtil;
import com.ericsson.common.util.serialization.View;
import com.ericsson.deviceaccess.api.genericdevice.GDAccessPermission.Type;
import com.ericsson.deviceaccess.api.genericdevice.GDException;
import com.ericsson.deviceaccess.api.genericdevice.GDProperties;
import com.ericsson.deviceaccess.api.genericdevice.GDPropertyMetadata;
import com.ericsson.deviceaccess.spi.genericdevice.GDAccessSecurity;
import com.ericsson.deviceaccess.spi.genericdevice.GDError;
import com.ericsson.deviceaccess.spi.impl.MetadataUtil;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class GDPropertiesImpl extends GDProperties.Stub implements GDProperties {

    public static final String LAST_UPDATE_TIME = "lastUpdateTime";
    private Map<String, Data> properties;
    //    private Map<String, GDPropertyMetadata> metadata;
    private GDServiceImpl parentService;

    public GDPropertiesImpl(Iterable<GDPropertyMetadata> metadataArray, GDServiceImpl parentService) {
        this.parentService = parentService;
        //        this.metadata = new HashMap<>();
        this.properties = new HashMap<>();
        if (metadataArray != null) {
            metadataArray.forEach(meta -> {
                properties.put(meta.getName(), new Data(meta).setToDefault());
            });
        }
    }

    public GDPropertiesImpl(Iterable<GDPropertyMetadata> metadataArray) {
        this(metadataArray, null);
    }

    @Override
    public boolean hasProperty(String name) {
        return properties.containsKey(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getValue(String name) {
        Data data = properties.get(name);
        if (data.currentValue == null) {
            data.setToDefault();
        }
        return data.currentValue;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getStringValue(String key) {
        Data data = properties.get(key);
        Object value = data.currentValue;
        if (value != null) {
            return String.valueOf(value);
        }
        return data.metadata.getDefaultStringValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setStringValue(String key, String value) {
        if (properties.get(key) == null) {
            throw new GDError("There is no property: " + key + " specified in the metadata for this property set.");
        }
        Class<?> type = properties.get(key).metadata.getType();
        if (Float.class.equals(type)) {
            setFloatValue(key, Float.parseFloat(value));
        } else if (Integer.class.equals(type)) {
            setIntValue(key, Integer.parseInt(value));
        } else {
            setValue(key, value);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setIntValue(String key, int value) {
        setValue(key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setLongValue(String key, long value) {
        setValue(key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setFloatValue(String key, float value) {
        setValue(key, value);
    }

    @JsonAnySetter
    public void setValue(String key, Object value) {
        MetadataUtil.INSTANCE.verifyPropertyAgainstMetadata(properties.get(key).metadata, key, value);
        properties.compute(key, (k, data) -> {
            tryNotifyChange(k, data.currentValue, value);
            data.currentValue = value;
            return data;
        });
    }

    private void tryNotifyChange(final String key, Object oldValue, final Object value) {
        properties.computeIfPresent(LAST_UPDATE_TIME, (k, data) -> {
            data.currentValue = System.currentTimeMillis();
            return data;
        });
        if (parentService != null && parentService.getParentDevice() != null) {
            if ((value == null && oldValue != null) || (value != null && !value.equals(oldValue))) {
                parentService.notifyEvent(new HashMap() {
                    {
                        put(key, value);
                    }
                });
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getIntValue(String key) {
        return getValue(key, Integer::parseInt, value -> value.intValue());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getLongValue(String key) {
        return getValue(key, Long::parseLong, value -> value.longValue());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public float getFloatValue(String key) {
        return getValue(key, Float::parseFloat, value -> value.floatValue());
    }

    private <T extends Number> T getValue(String key, Function<String, T> parser, Function<Number, T> getter) {
        Data data = properties.get(key);
        Object value = data.currentValue;
        Number defaultValue = data.metadata.getDefaultNumberValue();
        if (value instanceof String) {
            try {
                return parser.apply((String) value);
            } catch (NumberFormatException e) {
                return getter.apply(defaultValue);
            }
        } else if (value instanceof Number) {
            return getter.apply((Number) value);
        }
        return getter.apply(defaultValue);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getValueType(String key) {
        if (properties.containsKey(key)) {
            return properties.get(key).metadata.getTypeName();
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<String, Data> getProperties() {
        return Collections.unmodifiableMap(properties);
    }

    @Override
    public String serialize(Format format) throws GDException {
        GDAccessSecurity.checkPermission(getClass(), Type.GET);
        try {
            return SerializationUtil.execute(format,
                    mapper -> mapper.writerWithView(View.ID.Ignore.class).writeValueAsString(this));
        } catch (SerializationException ex) {
            throw new GDException(ex.getMessage(), ex);
        }
    }

    @Override
    public String serializeState() {
        try {
            return SerializationUtil.execute(Format.JSON,
                    mapper -> mapper.writerWithView(View.StatelessID.Ignore.class).writeValueAsString(this));
        } catch (SerializationException ex) {
            return "{}";
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addAll(GDProperties source) {
        source.getProperties().forEach((name, data) -> {
            Class type = data.metadata.getType();
            if (String.class.isAssignableFrom(type)) {
                setStringValue(name, source.getStringValue(name));
            } else if (Integer.class.isAssignableFrom(type)) {
                setIntValue(name, source.getIntValue(name));
            } else if (Float.class.isAssignableFrom(type)) {
                setFloatValue(name, source.getFloatValue(name));
            }
        });
    }

    public void addDynamicProperty(GDPropertyMetadata propertyMetadata) {
        properties.put(propertyMetadata.getName(), new Data(propertyMetadata).setToDefault());
        parentService.notifyEventAdded(propertyMetadata.getName());
    }

    public void removeDynamicProperty(GDPropertyMetadata propertyMetadata) {
        this.properties.remove(propertyMetadata.getName());
        parentService.notifyEventRemoved(propertyMetadata.getName());
    }
}