org.openmrs.cwf.api.property.PropertyService.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.cwf.api.property.PropertyService.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 * 
 * This Source Code Form is also subject to the terms of the Health-Related Additional
 * Disclaimer of Warranty and Limitation of Liability available at
 * http://www.carewebframework.org/licensing/disclaimer.
 */
package org.openmrs.cwf.api.property;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import org.carewebframework.api.property.IPropertyService;
import org.carewebframework.common.StrUtil;

import org.openmrs.GlobalProperty;
import org.openmrs.User;
import org.openmrs.api.context.Context;
import org.openmrs.util.PrivilegeConstants;

/**
 * OpenMRS implementation of property service. OpenMRS has two property stores, one for global
 * properties and one for user properties. The user property store has a limit of 255 characters for
 * a value. Therefore, we do some trickery here to split values longer than this into chunks,
 * storing the overflow chunks under the same property name suffixed with "^n" where n is
 * incremented for each overflow chunk.
 */
public class PropertyService implements IPropertyService {

    /**
     * Forms a property name from the base name and the instance name (if any).
     * 
     * @param propertyName The base property name.
     * @param instanceName The instance name (may be null).
     * @return The full qualified property name.
     */
    private String getPropertyName(String propertyName, String instanceName) {
        return instanceName == null ? propertyName : propertyName + "." + instanceName;
    }

    /**
     * Returns a global property instance given its name.
     * 
     * @param propertyName The global property name.
     * @param forceCreate If true, create the global property instance if it does not exist.
     * @return A global property instance.
     */
    private GlobalProperty getGlobalPropertyObject(String propertyName, boolean forceCreate) {
        GlobalProperty gp = Context.getAdministrationService().getGlobalPropertyObject(propertyName);

        if (gp == null && forceCreate) {
            gp = new GlobalProperty(propertyName);
        }

        return gp;
    }

    /**
     * Returns the value of a global property given its name.
     * 
     * @param propertyName Name of the global property.
     * @return The global property value, or null if it does not exist.
     */
    private String getGlobalPropertyValue(String propertyName) {
        return Context.getAdministrationService().getGlobalProperty(propertyName);
    }

    /**
     * Sets the value of a named global property.
     * 
     * @param propertyName Name of the global property.
     * @param value The property value.
     */
    private void setGlobalPropertyValue(String propertyName, String value) {
        try {
            Context.getUserContext().addProxyPrivilege(PrivilegeConstants.MANAGE_GLOBAL_PROPERTIES);
            GlobalProperty gp = getGlobalPropertyObject(propertyName, true);
            gp.setPropertyValue(value);
            Context.getAdministrationService().saveGlobalProperty(gp);
        } finally {
            Context.getUserContext().removeProxyPrivilege(PrivilegeConstants.MANAGE_GLOBAL_PROPERTIES);
        }
    }

    /**
     * Returns the value of a user property given its name.
     * 
     * @param propertyName Name of the user property.
     * @return The user property value, or null if it does not exist.
     */
    private String getUserPropertyValue(String propertyName) {
        User user = Context.getAuthenticatedUser();

        if (user == null) {
            return null;
        }

        StringBuilder sb = null;
        String value;

        while ((value = user.getUserProperty(propertyName, null)) != null) {
            sb = sb == null ? new StringBuilder() : sb;
            sb.append(value);
            propertyName = getNextPropertyName(propertyName);
        }

        return sb == null ? null : sb.toString();
    }

    /**
     * Returns the next property name in the series. This is used for chunking property values.
     * 
     * @param propertyName The current property name.
     * @return The next property name in the series.
     */
    private String getNextPropertyName(String propertyName) {
        String pcs[] = propertyName.split("\\^", 2);

        if (pcs.length == 1) {
            return propertyName + "^1";
        }

        return pcs[0] + "^" + (Integer.parseInt(pcs[1]) + 1);
    }

    /**
     * Sets the value of a named user property.
     * 
     * @param propertyName Name of the user property.
     * @param value The property value. Values in excess of 255 characters are chunked.
     */
    private void setUserPropertyValue(String propertyName, String value) {
        User user = Context.getAuthenticatedUser();

        if (user == null) {
            return;
        }

        boolean changed = false;

        for (int i = 0; i < value.length(); i += 255) {
            changed = true;
            user.setUserProperty(propertyName, StringUtils.substring(value, i, i + 255));
            propertyName = getNextPropertyName(propertyName);
        }

        while (user.getUserProperty(propertyName, null) != null) {
            changed = true;
            user.removeUserProperty(propertyName);
            propertyName = getNextPropertyName(propertyName);
        }

        if (changed) {
            try {
                Context.addProxyPrivilege(PrivilegeConstants.EDIT_USERS);
                Context.getUserService().saveUser(user, null);
            } finally {
                Context.removeProxyPrivilege(PrivilegeConstants.EDIT_USERS);
            }
        }
    }

    @Override
    public String getValue(String propertyName, String instanceName) {
        propertyName = getPropertyName(propertyName, instanceName);
        String value = getUserPropertyValue(propertyName);
        return value == null || value.isEmpty() ? getGlobalPropertyValue(propertyName) : value;
    }

    @Override
    public List<String> getValues(String propertyName, String instanceName) {
        String value = getValue(propertyName, instanceName);
        return value == null ? null : StrUtil.toList(value, null, "\n");
    }

    @Override
    public void saveValue(String propertyName, String instanceName, boolean asGlobal, String value) {
        propertyName = getPropertyName(propertyName, instanceName);

        if (asGlobal) {
            setGlobalPropertyValue(propertyName, value);
        } else {
            setUserPropertyValue(propertyName, value);
        }
    }

    @Override
    public void saveValues(String propertyName, String instanceName, boolean asGlobal, List<String> value) {
        saveValue(propertyName, instanceName, asGlobal, StrUtil.fromList(value));
    }

    @Override
    public List<String> getInstances(String propertyName, boolean asGlobal) {
        List<String> result = new ArrayList<String>();
        int len = propertyName.length();

        if (asGlobal) {
            List<GlobalProperty> gbs = Context.getAdministrationService().getGlobalPropertiesByPrefix(propertyName);

            if (gbs != null) {
                for (GlobalProperty gb : gbs) {
                    String name = gb.getProperty().substring(len);
                    result.add(name.startsWith(".") ? name.substring(1) : name);
                }
            }
        } else if (Context.isAuthenticated()) {
            Map<String, String> map = Context.getUserContext().getAuthenticatedUser().getUserProperties();

            if (map != null) {
                for (String name : map.keySet()) {
                    if (name.startsWith(propertyName) && !name.contains("^")) {
                        name = name.substring(len);
                        result.add(name.startsWith(".") ? name.substring(1) : name);
                    }
                }
            }
        }

        return result;
    }

    @Override
    public boolean isAvailable() {
        return true;
    }

}