Backable Encapsulators


Table of Contents

Introduction

Encapsulators are queues with extended functionality. As the name suggests, encapsulators are used to encapsulate data in them, they let the telemonitoring system store data. These encapsulators enable the telemonitoring system to get callbacks on the event that a data point is added or removed, the encapsulator became empty or full and more. Furthermore, encapsulators are backable, allowing them to get support from our backup cabinets for background backup and restoration capabilities. Finally, encapsulators are thread-safe.The PrivacyMechanism mPDI object is used for protecting client sensitive data.

In this tutorial, we demonstrate the basic functionality, handling and capabilities of backable encapsulators.

Basic functionality and handling

Encapsulators allow telemonitoring applications to store data, where each data point has a unique serial number (unique among all other data points in the same encapsulator). Encapsulators support having maximum capacity as well (which by default is infinity). Encapsulators are generic data structures with the generic type T being the type of the data to be stored in the encapsulator.

Since encapsulators are also backable data structures, every encapsulator must be identified by a backable identifier. These identifiers are used for purposes of book keeping should the backable need to be backed up or restore from previous backup. Let’s create an identifier called dataID  using the standard string encapsulator identifier (BackableEncapsulatorIdentifier) as follows: BackableEncapsulatorIdentifier dataID = new BackableEncapsulatorIdentifier(“my data”);

The constructor BackableEncapsulator(dataID) is used to initialize an encapsulator, identifier by dataID, with infinite capacity, whereas the constructor BackableEncapsulator(dataID, cap) is used to initialize an encapsulator, identified by dataID with capacity cap.

Adding data

Once an encapsulator has been created, you can use addData(T datapoint) to add the data in datapoint to the encapsulator. This method will return the serial number of the data point inside the encapsulator if it succeeds. The method will throw an IllegalStateException if the encapsulator is full.

Adding data (sensitive data)

For adding sensitive data to the encapsulator created, you can use addData(T datapoint, PrivateClass c)  to add the sanitized data in  datapoint to the encapsulator. This method will return the serial number of the data point inside the encapsulator if it succeeds. The method will throw IllegalStateException  if the encapsulator is full; PrivacyMechanismException  if the input PrivateClass  is not in the predefined category list in the PrivacyMechanism ; NullPointerException  if the Privacy Mechanism mPDI  object is null.

Removing data

There are multiple ways that can be used to remove data from the encapsulator. One option is to remove the item in the head of the queue by using popFirst() or popFirst(PrivateClass c) . The popFirst()  can return insensitive data without PrivateMechanism  from the encapsulator. The popFirst(PrivateClass c) can return desanitized data from the encapsulator. If the encapsulator is empty, the method will throw an IllegalStateExceptionIf the input PrivateClass  is not in the predefined category list in the PrivacyMechanism , the method will throw a PrivacyMechanismException . If the the PrivateMechanism mPDI object is null, i.e. the data belongs to sensitive data but calling popFirst(PrivateClass c) , the method will throw a NullPointerException Otherwise, the popFirst() or popFirst (PrivateClass c) method will remove the first data point from the encapsulator and return the original data or desanitized data along with its serial number in a data serial pair object of type DataSerialPair<T>.

Another way to remove a data point from an encapsulator is by using its serial number. This can be done by using removeData(long serialNumber), which will throw an IllegalStateException if the serial number serialNumber does not exist in the encapsulator. Otherwise, the method will remove the data point associated with the serial number serialNumber.

Finally, the method flushData() can be used to remove all data points from the encapsulator at once.

Retrieving a data point

There are two main ways to retrieve a data point from an encapsulator. The first way is by using getFirst() for insensitive data or getFirst(PrivateClass c)  for sensitive data, which returns a DataSerialPair<T> object representing the head (first data point) of the encapsulator if the encapsulator is not empty. Otherwise, the method will throw an IllegalStateException.

Alternatively, the method getDatapoint(long serialNumber) will return the data point (directly as type T, not DataSerialPair<T>) corresponding to the serial number serialNumber, if it exists. Otherwise, the method will throw an IllegalStateExceptionSimilarly, getDatapoint(long serialNumber, PrivateClass c)  will return the desanitized data point as type T  corresponding to the serial number serialNumber . If the PrivateClass c  is not in the predefined category list in the PrivacyMechanism , the method will throw a PrivacyMechanismException . If the Privacy mechanism mPDI  object is null, the method will throw a NullPointerException .

Iterating over the data

The encapsulator is an iterable class. This means that you can iterate over all the data points in the encapsulator by using a for loop as follows. The returned datapoints from an iterator are not desanitized, they’re returned as is

// Iterate over the data
for (DataSerialPair<T> dataSer : encapsulator) {
	// Do what you wish with dataSer
}

PrivacyMechanism

The PrivacyMechanism  is an mPDI  object associated with the class BackableEncapsulator  (only mandatory for client sensitive data). We create the mPDI  object using PrivacyMechanismInterface  which represents the PrivacyMechanism  structure. The PrivacyMechanism  structure includes sanitize method sanitize(PrivateClass c, T original)  and  desanitize method desanitize(PrivateClass c, T sanitized). Both methods can manipulate data points of generic type T based on the PrivateClass c .

The sanitizate represents the process of encoding data and the desanitize method represents the process of decoding data using Privacy Mapping Functions (PMF) which are generated by a computational software MATLAB. The MATLAB implements as a toolbox. The PMF can shuffle the  categories of the sensitive data in the class BackableEncapsulator .

Example of basic functionality

Testing code without privacy mechanism together, consider the output of the following code:

// Create an identifier
BackableEncapsulatorIdentifier dataID = new BackableEncapsulatorIdentifier("my data");
// Create the encapsulator
BackableEncapsulator<Integer> myEnc = new BackableEncapsulator<Integer>(dataID, 3);
try {
	// Add the number 2
	myEnc.addData(2);
	// Add the number 10
	myEnc.addData(10);
	// Pop first
	DataSerialPair<Integer> popped = myEnc.popFirst();
	// Print it
	System.out.println(popped.getDatapoint().toString());
	// The data point serial number is in popped.getSerial()
	// Add the number 300
	long serialNumber = myEnc.addData(300);
	// Add the number 1100
	myEnc.addData(1100);
	// Remove the number 300 through the serial number
	myEnc.removeData(serialNumber);
	// Add the number 3030
	myEnc.addData(3030);
	// Add the number 7700
	myEnc.addData(7700);
} catch (IllegalStateException e) {
	System.out.println("Encapsulator is full!");
}

// Iterate over the data
for (DataSerialPair<Integer> dataSer : myEnc) {
	// Get the serial number (for demonstration)
	long serial = dataSer.getSerial();
	// Get the data point (the number)
	Integer datapoint = dataSer.getDatapoint();
	// And print
	System.out.println(datapoint.toString());
}

What would this code print?

2
Encapsulator is full!
10
1100
3030

Testing code with privacy mechanism together, consider the output of the following code:

package edu.berkeley.telemonitoring.core.backableencapsulator;

        import org.junit.Test;

        import java.io.IOException;
        import java.io.NotSerializableException;

        import edu.berkeley.telemonitoring.core.dataencapsulator.DataSerialPair;
        import edu.berkeley.telemonitoring.core.privacy.PrivacyMechanismException;
        import edu.berkeley.telemonitoring.core.privacy.PrivacyMechanismInterface;
        import edu.berkeley.telemonitoring.core.privacy.PrivateClass;
        import edu.berkeley.telemonitoring.core.util.StringIdentifier;

/**
 * This class is for testing the functionality of the PrivacyMechanismInterface and methods relating to pdi in BackableEncapsulator.
 * Created by Kaidi Du on 4/4/17.
 */
public class PrivacyTestUnit {

    /**
     * Test the functionality of the PrivacyMechanism including Sanitization and Desanitization methods.
     */
    @Test
    public void sanitizeDesanitizeTest() {
        SanitizeDesanitize t1 = new SanitizeDesanitize();
        PrivateClass c1 = new PrivateClass("c1");
        PrivateClass c2 = new PrivateClass("c2");
        Double Test0 = 1.0;
        Double Test0_Sanitized1 = 2.0;
        Double Test0_Sanitized2 = -2.0;
        Double t1_Sanitize = t1.sanitize(c1, Test0);
        System.out.println(t1_Sanitize); //Test0_Sanitized1
        Double t2_Sanitize = t1.sanitize(c2, Test0);
        System.out.println(t2_Sanitize); //Test0_Sanitized2

        Double t1_Desanitize = t1.desanitize(c1, Test0_Sanitized1);
        System.out.println(t1_Desanitize);//Test0
        t1_Desanitize = t1.desanitize(c2, Test0_Sanitized2);
        System.out.println(t1_Desanitize);//Test0
    }


    /**
     * Test the functionality of the methods relating to PrivacyMechanism in the BackableEncapsulator.
     */
    @Test
    public void backableEncapsulatorTest() {
        PrivacyMechanismInterface<Double> pdi = new SanitizeDesanitize();
        BackableEncapsulatorIdentifierInterface mDataID = new StringIdentifier("c1");
        BackableEncapsulator<Double> t1 = new BackableEncapsulator(mDataID, pdi);
        PrivateClass c1 = new PrivateClass("c1");
        PrivateClass c2 = new PrivateClass("c2");
        //add data
        Double Test0 = 1.0;
        Double Test1 = 2.0;
        Double Test2 = 3.0;
        long t1_index0 = t1.addData(Test0);
        long t1_index1 = t1.addData(Test1, c1);
        long t1_index2 = t1.addData(Test2, c2);

        //get data
        Double t1_Data = t1.getData(t1_index0);
        System.out.println(t1_Data);//Test0
        t1_Data = t1.getData(t1_index1, c1);
        System.out.println(t1_Data);//Test1
        t1_Data = t1.getData(t1_index2, c2);
        System.out.println(t1_Data);//Test2
        //get first and pop first
        DataSerialPair<Double> t1_getF = t1.getFirst();
        System.out.println(t1_getF.getDatapoint());//Test0
        DataSerialPair<Double> t1_pop = t1.popFirst();
        System.out.println(t1_getF.getDatapoint());//Test0
        t1_getF = t1.getFirst(c1);
        System.out.println(t1_getF.getDatapoint());//Test1
        t1_pop = t1.popFirst(c1);
        System.out.println(t1_pop.getDatapoint());//Test1
        t1_pop = t1.popFirst(c2);
        System.out.println(t1_pop.getDatapoint());//Test2
    }


    /**
     * Test the results of restoring BackableEncapsulator and deep copying the pdi object.
     * @throws IllegalArgumentException
     * @throws ClassNotFoundException
     * @throws IOException
     */
    @Test
    public void backableEncapsulatorRestoreDataFromObjectTest()throws IllegalArgumentException, NotSerializableException, ClassNotFoundException, IOException{
        SanitizeDesanitize pdi1 = new SanitizeDesanitize();
        SanitizeDesanitize pdi2 = new SanitizeDesanitize();
        BackableEncapsulatorIdentifierInterface mDataID = new StringIdentifier("c1");
        pdi1.testNUmset(1);
        pdi2.testNUmset(2);
        BackableEncapsulator<Double> t1 = new BackableEncapsulator(mDataID, pdi1);
        BackableEncapsulator<Double> t2 = new BackableEncapsulator(mDataID, pdi2);
        PrivateClass c1 = new PrivateClass("c1");
        PrivateClass c2 = new PrivateClass("c2");

        // Resorting/copying BackableEncapsulator t1 to t2
        t2.restoreDataFromObject(t1);

        // Now let's retreive the PDI object
        PrivacyMechanismInterface<?> pdiRet = t2.getPDI();
        SanitizeDesanitize pdiRetActual = (SanitizeDesanitize) pdiRet;
        System.out.println(pdi1.testNUmsetresult());//1
        System.out.println(pdiRetActual.testNUmsetresult());//1
        System.out.println(pdi2.testNUmsetresult());//2
        pdi1.testNUmset(3);
        System.out.println(pdi1.testNUmsetresult());//3
        System.out.println(pdi2.testNUmsetresult());//2
        System.out.println(pdiRetActual.testNUmsetresult());//1

    }

    /**
     * An instantiation of PirvacyMechanism Interface
     */
    public static class SanitizeDesanitize implements PrivacyMechanismInterface<Double> {
        private static final long serialVersionUID = -1142879218068383841L;
        private PrivateClass classC1 = new PrivateClass("c1");
        private PrivateClass classC2 = new PrivateClass("c2");
        public int testNum;

        /**
         * Sanitize the data points based to hide the category of the data points.
         * @param c The category of the original data points which we would like to hide.
         * @param original The original data points.
         * @return Sanitized data points which hide the category.
         * @throws PrivacyMechanismException
         */
        public Double sanitize(PrivateClass c, Double original) throws PrivacyMechanismException {
            if (c.equals(classC1)) {
                return 2 * original;
            } else if (c.equals(classC2)){
                return -2 * original;
            } else {
                throw new PrivacyMechanismException("Error! Your choice is not in the list");
            }
        }

        /**
         * Desanitize the data points to retrieve the hidden category.
         * @param c The category of the original data points.
         * @param sanitized The sanitized data points.
         * @return Desanitized data points which retrieve the category.
         * @throws PrivacyMechanismException
         */
        public Double desanitize(PrivateClass c, Double sanitized) throws PrivacyMechanismException {

            if (c.equals(classC1)) { //Update
                return 1.0/2 * sanitized;
            } else if (c.equals(classC2)){
                return -1.0/2 * sanitized;
            } else {
                throw new PrivacyMechanismException("Error! Your choice is not in the list");
            }
        }

        public void testNUmset(int val){
            this.testNum = val;
        }
        public int testNUmsetresult(){
            return this.testNum;
        }
    }
}

What would this code print?

2.0
-2.0
1.0
1.0
1
1
2
3
2
1
1.0
2.0
3.0
1.0
1.0
2.0
2.0
3.0

Basic capabilities

Events (TODO: finish)