blob: 734eb0c119d4948ab0c4110bdb80653cb630ba86 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sysds.runtime.privacy;
import java.util.*;
import org.apache.sysds.parser.DataExpression;
import org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
import org.apache.sysds.runtime.instructions.Instruction;
import org.apache.sysds.runtime.instructions.cp.AggregateBinaryCPInstruction;
import org.apache.sysds.runtime.instructions.cp.AggregateUnaryCPInstruction;
import org.apache.sysds.runtime.instructions.cp.BinaryCPInstruction;
import org.apache.sysds.runtime.instructions.cp.BuiltinNaryCPInstruction;
import org.apache.sysds.runtime.instructions.cp.CPInstruction;
import org.apache.sysds.runtime.instructions.cp.CPOperand;
import org.apache.sysds.runtime.instructions.cp.ComputationCPInstruction;
import org.apache.sysds.runtime.instructions.cp.CovarianceCPInstruction;
import org.apache.sysds.runtime.instructions.cp.Data;
import org.apache.sysds.runtime.instructions.cp.FunctionCallCPInstruction;
import org.apache.sysds.runtime.instructions.cp.MultiReturnParameterizedBuiltinCPInstruction;
import org.apache.sysds.runtime.instructions.cp.ParameterizedBuiltinCPInstruction;
import org.apache.sysds.runtime.instructions.cp.MultiReturnBuiltinCPInstruction;
import org.apache.sysds.runtime.instructions.cp.QuaternaryCPInstruction;
import org.apache.sysds.runtime.instructions.cp.SqlCPInstruction;
import org.apache.sysds.runtime.instructions.cp.UnaryCPInstruction;
import org.apache.sysds.runtime.instructions.cp.VariableCPInstruction;
import org.apache.sysds.runtime.matrix.data.MatrixBlock;
import org.apache.sysds.runtime.privacy.PrivacyConstraint.PrivacyLevel;
import org.apache.sysds.runtime.privacy.finegrained.DataRange;
import org.apache.sysds.runtime.privacy.finegrained.FineGrainedPrivacy;
import org.apache.wink.json4j.JSONException;
import org.apache.wink.json4j.JSONObject;
/**
* Class with static methods merging privacy constraints of operands
* in expressions to generate the privacy constraints of the output.
*/
public class PrivacyPropagator
{
public static Data parseAndSetPrivacyConstraint(Data cd, JSONObject mtd)
throws JSONException
{
if ( mtd.containsKey(DataExpression.PRIVACY) ) {
String privacyLevel = mtd.getString(DataExpression.PRIVACY);
if ( privacyLevel != null )
cd.setPrivacyConstraints(new PrivacyConstraint(PrivacyLevel.valueOf(privacyLevel)));
}
return cd;
}
public static PrivacyConstraint mergeBinary(PrivacyConstraint privacyConstraint1, PrivacyConstraint privacyConstraint2) {
if (privacyConstraint1 != null && privacyConstraint2 != null){
PrivacyLevel privacyLevel1 = privacyConstraint1.getPrivacyLevel();
PrivacyLevel privacyLevel2 = privacyConstraint2.getPrivacyLevel();
// One of the inputs are private, hence the output must be private.
if (privacyLevel1 == PrivacyLevel.Private || privacyLevel2 == PrivacyLevel.Private)
return new PrivacyConstraint(PrivacyLevel.Private);
// One of the inputs are private with aggregation allowed, but none of the inputs are completely private,
// hence the output must be private with aggregation.
else if (privacyLevel1 == PrivacyLevel.PrivateAggregation || privacyLevel2 == PrivacyLevel.PrivateAggregation)
return new PrivacyConstraint(PrivacyLevel.PrivateAggregation);
// Both inputs have privacy level "None", hence the privacy constraint can be removed.
else
return null;
}
else if (privacyConstraint1 != null)
return privacyConstraint1;
else if (privacyConstraint2 != null)
return privacyConstraint2;
return null;
}
public static PrivacyConstraint mergeNary(PrivacyConstraint[] privacyConstraints){
PrivacyConstraint mergedPrivacyConstraint = privacyConstraints[0];
for ( int i = 1; i < privacyConstraints.length; i++ ){
mergedPrivacyConstraint = mergeBinary(mergedPrivacyConstraint, privacyConstraints[i]);
}
return mergedPrivacyConstraint;
}
public static Instruction preprocessInstruction(Instruction inst, ExecutionContext ec){
switch ( inst.getType() ){
case CONTROL_PROGRAM:
return preprocessCPInstructionFineGrained( (CPInstruction) inst, ec );
case BREAKPOINT:
case SPARK:
case GPU:
case FEDERATED:
return inst;
default:
throwExceptionIfPrivacyActivated(inst);
return inst;
}
}
public static Instruction preprocessCPInstructionFineGrained(CPInstruction inst, ExecutionContext ec){
switch ( inst.getCPInstructionType() ){
case AggregateBinary:
if ( inst instanceof AggregateBinaryCPInstruction ){
// This can only be a matrix multiplication and it does not count as an aggregation in terms of privacy.
return preprocessAggregateBinaryCPInstruction((AggregateBinaryCPInstruction)inst, ec);
} else if ( inst instanceof CovarianceCPInstruction ){
return preprocessCovarianceCPInstruction((CovarianceCPInstruction)inst, ec);
} else preprocessInstructionSimple(inst, ec);
case AggregateTernary:
//TODO: Support propagation of fine-grained privacy constraints
return preprocessTernaryCPInstruction((ComputationCPInstruction) inst, ec);
case AggregateUnary:
// Assumption: aggregates in one or several dimensions, number of dimensions may change, only certain slices of the data may be aggregated upon, elements do not change position
return preprocessAggregateUnaryCPInstruction((AggregateUnaryCPInstruction)inst, ec);
case Append:
case Binary:
// TODO: Support propagation of fine-grained privacy constraints
return preprocessBinaryCPInstruction((BinaryCPInstruction) inst, ec);
case Builtin:
case BuiltinNary:
//TODO: Support propagation of fine-grained privacy constraints
return preprocessBuiltinNary((BuiltinNaryCPInstruction) inst, ec);
/*case CentralMoment:
break;
case Compression:
break;
case Covariance:
break;
case Ctable:
break;
case Dnn:
break;
*/
case FCall:
//TODO: Support propagation of fine-grained privacy constraints
return preprocessExternal((FunctionCallCPInstruction) inst, ec);
/*
case MMChain:
break;
case MMTSJ:
break;
case MatrixIndexing:
break;*/
case MultiReturnBuiltin:
case MultiReturnParameterizedBuiltin:
// TODO: Support propagation of fine-grained privacy constraints
return preprocessMultiReturn((ComputationCPInstruction)inst, ec);
/*case PMMJ:
break;*/
case ParameterizedBuiltin:
// TODO: Support propagation of fine-grained privacy constraints
return preprocessParameterizedBuiltin((ParameterizedBuiltinCPInstruction) inst, ec);
/*case Partition:
break;
case QPick:
break;
case QSort:
break;*/
case Quaternary:
// TODO: Support propagation of fine-grained privacy constraints
return preprocessQuaternary((QuaternaryCPInstruction) inst, ec);
/*case Rand:
break;*/
case Reorg:
// TODO: Support propagation of fine-grained privacy constraints
return preprocessUnaryCPInstruction((UnaryCPInstruction) inst, ec);
/*case Reshape:
break;
case SpoofFused:
break;
case Sql:
break;
case StringInit:
break;*/
case Ternary:
// TODO: Support propagation of fine-grained privacy constraints
return preprocessTernaryCPInstruction((ComputationCPInstruction) inst, ec);
/*case UaggOuterChain:
break;*/
case Unary:
// Assumption: No aggregation, elements do not change position, no change of dimensions
return preprocessUnaryCPInstruction((UnaryCPInstruction) inst, ec);
case Variable:
return preprocessVariableCPInstruction((VariableCPInstruction) inst, ec);
default:
return preprocessInstructionSimple(inst, ec);
}
}
/**
* Throw exception if privacy constraint activated for instruction or for input to instruction.
* @param inst covariance instruction
* @param ec execution context
* @return input instruction if privacy constraints are not activated
*/
private static Instruction preprocessCovarianceCPInstruction(CovarianceCPInstruction inst, ExecutionContext ec){
throwExceptionIfPrivacyActivated(inst);
for ( CPOperand input : inst.getInputs() ){
PrivacyConstraint privacyConstraint = getInputPrivacyConstraint(ec, input);
if ( privacyConstraint != null){
throw new DMLPrivacyException("Input of instruction " + inst + " has privacy constraints activated, but the constraints are not propagated during preprocessing of instruction.");
}
}
return inst;
}
private static Instruction preprocessAggregateBinaryCPInstruction(AggregateBinaryCPInstruction inst, ExecutionContext ec){
PrivacyConstraint privacyConstraint1 = getInputPrivacyConstraint(ec, inst.input1);
PrivacyConstraint privacyConstraint2 = getInputPrivacyConstraint(ec, inst.input2);
if ( (privacyConstraint1 != null && privacyConstraint1.hasConstraints())
|| (privacyConstraint2 != null && privacyConstraint2.hasConstraints()) ){
PrivacyConstraint mergedPrivacyConstraint;
if ( (privacyConstraint1 != null && privacyConstraint1.hasFineGrainedConstraints() ) || (privacyConstraint2 != null && privacyConstraint2.hasFineGrainedConstraints() )){
MatrixBlock input1 = ec.getMatrixInput(inst.input1.getName());
MatrixBlock input2 = ec.getMatrixInput(inst.input2.getName());
mergedPrivacyConstraint = matrixMultiplicationPropagation(input1, privacyConstraint1, input2, privacyConstraint2);
}
else {
mergedPrivacyConstraint = mergeBinary(privacyConstraint1, privacyConstraint2);
inst.setPrivacyConstraint(mergedPrivacyConstraint);
}
inst.output.setPrivacyConstraint(mergedPrivacyConstraint);
}
return inst;
}
public static Instruction preprocessBinaryCPInstruction(BinaryCPInstruction inst, ExecutionContext ec){
PrivacyConstraint privacyConstraint1 = getInputPrivacyConstraint(ec, inst.input1);
PrivacyConstraint privacyConstraint2 = getInputPrivacyConstraint(ec, inst.input2);
if ( privacyConstraint1 != null || privacyConstraint2 != null) {
PrivacyConstraint mergedPrivacyConstraint = mergeBinary(privacyConstraint1, privacyConstraint2);
inst.setPrivacyConstraint(mergedPrivacyConstraint);
inst.output.setPrivacyConstraint(mergedPrivacyConstraint);
}
return inst;
}
/**
* Return the merged fine-grained privacy constraint of a matrix multiplication with the given privacy constraints.
* The current implementation has a tendency to create small ranges of privacy level private. These ranges could be merged
* to create fewer ranges spanning the same elements.
* @param input1 first input matrix block
* @param privacyConstraint1 privacy constraint of the first matrix
* @param input2 second input matrix block
* @param privacyConstraint2 privacy constraint of the second matrix
* @return merged privacy constraint
*/
public static PrivacyConstraint matrixMultiplicationPropagation(MatrixBlock input1, PrivacyConstraint privacyConstraint1, MatrixBlock input2, PrivacyConstraint privacyConstraint2){
// If the overall privacy level is private, then the fine-grained constraints do not have to be checked.
if ( (privacyConstraint1 != null && privacyConstraint1.getPrivacyLevel() == PrivacyLevel.Private) || (privacyConstraint2 != null && privacyConstraint2.getPrivacyLevel() == PrivacyLevel.Private) )
return new PrivacyConstraint(PrivacyLevel.Private);
boolean hasOverallConstraintAggregate = ( (privacyConstraint1 != null && privacyConstraint1.getPrivacyLevel() == PrivacyLevel.PrivateAggregation ) || ( privacyConstraint2 != null && privacyConstraint2.getPrivacyLevel() == PrivacyLevel.PrivateAggregation));
PrivacyConstraint mergedConstraint = new PrivacyConstraint();
if ( hasOverallConstraintAggregate )
mergedConstraint.setPrivacyLevel(PrivacyLevel.PrivateAggregation);
int r1 = input1.getNumRows();
int c1 = input1.getNumColumns();
int r2 = input2.getNumRows();
int c2 = input2.getNumColumns();
FineGrainedPrivacy mergedFineGrainedConstraints = mergedConstraint.getFineGrainedPrivacy();
for (int i = 0; i < r1; i++){
// Get privacy of first matrix row
long[] beginRange1 = new long[]{i,0};
long[] endRange1 = new long[]{i,c1};
Map<DataRange, PrivacyLevel> privacyInRow = (privacyConstraint1 != null) ? privacyConstraint1.getFineGrainedPrivacy().getPrivacyLevel(new DataRange(beginRange1, endRange1)) : new HashMap<>();
for (int j = 0; j < c2; j++){
// Get Privacy of Second matrix col
long[] beginRange2 = new long[]{0,j};
long[] endRange2 = new long[]{r2,j};
Map<DataRange, PrivacyLevel> privacyInCol = (privacyConstraint2 != null) ? privacyConstraint2.getFineGrainedPrivacy().getPrivacyLevel(new DataRange(beginRange2, endRange2)) : new HashMap<>();
// if any elements in the row or col has privacy level private or privateaggregate,
// then output element in the index should be same level.
long[] beginRangeMerged = new long[]{i,j};
long[] endRangeMerged = new long[]{i,j};
if ( privacyInRow.containsValue(PrivacyLevel.Private) || privacyInCol.containsValue(PrivacyLevel.Private))
mergedFineGrainedConstraints.put(new DataRange(beginRangeMerged, endRangeMerged), PrivacyLevel.Private);
else if ( !hasOverallConstraintAggregate && (privacyInRow.containsValue(PrivacyLevel.PrivateAggregation) || privacyInCol.containsValue(PrivacyLevel.PrivateAggregation) ))
mergedFineGrainedConstraints.put(new DataRange(beginRangeMerged, endRangeMerged), PrivacyLevel.PrivateAggregation);
}
}
return mergedConstraint;
}
/**
* Propagate privacy constraint to output if any of the elements are private.
* Privacy constraint is always propagated to instruction.
* @param inst aggregate instruction
* @param ec execution context
* @return updated instruction with propagated privacy constraints
*/
private static Instruction preprocessAggregateUnaryCPInstruction(AggregateUnaryCPInstruction inst, ExecutionContext ec){
PrivacyConstraint privacyConstraint = getInputPrivacyConstraint(ec, inst.input1);
if ( privacyConstraint != null ) {
inst.setPrivacyConstraint(privacyConstraint);
if ( inst.output != null){
//Only propagate to output if any of the elements are private.
//It is an aggregation, hence the constraint can be removed in case of any other privacy level.
if(privacyConstraint.hasPrivateElements())
inst.output.setPrivacyConstraint(new PrivacyConstraint(PrivacyLevel.Private));
}
}
return inst;
}
/**
* Throw exception if privacy constraints are activated or return instruction if privacy is not activated
* @param inst instruction
* @param ec execution context
* @return instruction
*/
public static Instruction preprocessInstructionSimple(Instruction inst, ExecutionContext ec){
throwExceptionIfPrivacyActivated(inst);
return inst;
}
public static Instruction preprocessExternal(FunctionCallCPInstruction inst, ExecutionContext ec){
return mergePrivacyConstraintsFromInput(
inst,
ec,
inst.getInputs(),
inst.getBoundOutputParamNames().toArray(new String[0])
);
}
public static Instruction preprocessMultiReturn(ComputationCPInstruction inst, ExecutionContext ec){
List<CPOperand> outputs = getOutputOperands(inst);
return mergePrivacyConstraintsFromInput(inst, ec, inst.getInputs(), outputs);
}
public static Instruction preprocessParameterizedBuiltin(ParameterizedBuiltinCPInstruction inst, ExecutionContext ec){
return mergePrivacyConstraintsFromInput(inst, ec, inst.getInputs(), inst.getOutput() );
}
private static Instruction mergePrivacyConstraintsFromInput(Instruction inst, ExecutionContext ec, CPOperand[] inputs, String[] outputNames){
if ( inputs != null && inputs.length > 0 ){
PrivacyConstraint[] privacyConstraints = getInputPrivacyConstraints(ec, inputs);
if ( privacyConstraints != null ){
PrivacyConstraint mergedPrivacyConstraint = mergeNary(privacyConstraints);
inst.setPrivacyConstraint(mergedPrivacyConstraint);
if ( outputNames != null ){
for (String outputName : outputNames)
setOutputPrivacyConstraint(ec, mergedPrivacyConstraint, outputName);
}
}
}
return inst;
}
private static Instruction mergePrivacyConstraintsFromInput(Instruction inst, ExecutionContext ec, CPOperand[] inputs, CPOperand output){
return mergePrivacyConstraintsFromInput(inst, ec, inputs, getSingletonList(output));
}
private static Instruction mergePrivacyConstraintsFromInput(Instruction inst, ExecutionContext ec, CPOperand[] inputs, List<CPOperand> outputs){
if ( inputs != null && inputs.length > 0 ){
PrivacyConstraint[] privacyConstraints = getInputPrivacyConstraints(ec, inputs);
if ( privacyConstraints != null ){
PrivacyConstraint mergedPrivacyConstraint = mergeNary(privacyConstraints);
inst.setPrivacyConstraint(mergedPrivacyConstraint);
for ( CPOperand output : outputs ){
if ( output != null ) {
output.setPrivacyConstraint(mergedPrivacyConstraint);
}
}
}
}
return inst;
}
public static Instruction preprocessBuiltinNary(BuiltinNaryCPInstruction inst, ExecutionContext ec){
return mergePrivacyConstraintsFromInput(inst, ec, inst.getInputs(), inst.getOutput() );
}
public static Instruction preprocessQuaternary(QuaternaryCPInstruction inst, ExecutionContext ec){
return mergePrivacyConstraintsFromInput(
inst,
ec,
new CPOperand[] {inst.input1,inst.input2,inst.input3,inst.getInput4()},
inst.output
);
}
public static Instruction preprocessTernaryCPInstruction(ComputationCPInstruction inst, ExecutionContext ec){
return mergePrivacyConstraintsFromInput(inst, ec, inst.getInputs(), inst.output);
}
public static Instruction preprocessUnaryCPInstruction(UnaryCPInstruction inst, ExecutionContext ec){
return propagateInputPrivacy(inst, ec, inst.input1, inst.output);
}
public static Instruction preprocessVariableCPInstruction(VariableCPInstruction inst, ExecutionContext ec){
switch ( inst.getVariableOpcode() ) {
case CreateVariable:
return propagateSecondInputPrivacy(inst, ec);
case AssignVariable:
return propagateInputPrivacy(inst, ec, inst.getInput1(), inst.getInput2());
case CopyVariable:
case MoveVariable:
case RemoveVariableAndFile:
case CastAsMatrixVariable:
case CastAsFrameVariable:
case Write:
case SetFileName:
return propagateFirstInputPrivacy(inst, ec);
case RemoveVariable:
return propagateAllInputPrivacy(inst, ec);
case CastAsScalarVariable:
case CastAsDoubleVariable:
case CastAsIntegerVariable:
case CastAsBooleanVariable:
return propagateCastAsScalarVariablePrivacy(inst, ec);
case Read:
return inst;
default:
throwExceptionIfPrivacyActivated(inst);
return inst;
}
}
private static void throwExceptionIfPrivacyActivated(Instruction inst){
if ( inst.getPrivacyConstraint() != null && inst.getPrivacyConstraint().hasConstraints() ) {
throw new DMLPrivacyException("Instruction " + inst + " has privacy constraints activated, but the constraints are not propagated during preprocessing of instruction.");
}
}
/**
* Propagate privacy from first input.
* @param inst Instruction
* @param ec execution context
* @return instruction with or without privacy constraints
*/
private static Instruction propagateCastAsScalarVariablePrivacy(VariableCPInstruction inst, ExecutionContext ec){
inst = (VariableCPInstruction) propagateFirstInputPrivacy(inst, ec);
return inst;
}
/**
* Propagate privacy constraints from all inputs if privacy constraints are set.
* @param inst instruction
* @param ec execution context
* @return instruction with or without privacy constraints
*/
private static Instruction propagateAllInputPrivacy(VariableCPInstruction inst, ExecutionContext ec){
return mergePrivacyConstraintsFromInput(
inst, ec, inst.getInputs().toArray(new CPOperand[0]), inst.getOutput());
}
/**
* Propagate privacy constraint to instruction and output of instruction
* if data of first input is CacheableData and
* privacy constraint is activated.
* @param inst VariableCPInstruction
* @param ec execution context
* @return instruction with or without privacy constraints
*/
private static Instruction propagateFirstInputPrivacy(VariableCPInstruction inst, ExecutionContext ec){
return propagateInputPrivacy(inst, ec, inst.getInput1(), inst.getOutput());
}
/**
* Propagate privacy constraint to instruction and output of instruction
* if data of second input is CacheableData and
* privacy constraint is activated.
* @param inst VariableCPInstruction
* @param ec execution context
* @return instruction with or without privacy constraints
*/
private static Instruction propagateSecondInputPrivacy(VariableCPInstruction inst, ExecutionContext ec){
return propagateInputPrivacy(inst, ec, inst.getInput2(), inst.getOutput());
}
/**
* Propagate privacy constraint to instruction and output of instruction
* if data of the specified variable is CacheableData
* and privacy constraint is activated
* @param inst instruction
* @param ec execution context
* @param inputOperand input from which the privacy constraint is found
* @param outputOperand output which the privacy constraint is propagated to
* @return instruction with or without privacy constraints
*/
private static Instruction propagateInputPrivacy(Instruction inst, ExecutionContext ec, CPOperand inputOperand, CPOperand outputOperand){
PrivacyConstraint privacyConstraint = getInputPrivacyConstraint(ec, inputOperand);
if ( privacyConstraint != null ) {
inst.setPrivacyConstraint(privacyConstraint);
if ( outputOperand != null)
outputOperand.setPrivacyConstraint(privacyConstraint);
}
return inst;
}
/**
* Get privacy constraint of input data variable from execution context.
* @param ec execution context from which the data variable is retrieved
* @param input data variable from which the privacy constraint is retrieved
* @return privacy constraint of variable or null if privacy constraint is not set
*/
private static PrivacyConstraint getInputPrivacyConstraint(ExecutionContext ec, CPOperand input){
if ( input != null && input.getName() != null){
Data dd = ec.getVariable(input.getName());
if ( dd != null )
return dd.getPrivacyConstraint();
}
return null;
}
private static PrivacyConstraint[] getInputPrivacyConstraints(ExecutionContext ec, CPOperand[] inputs){
if ( inputs != null && inputs.length > 0){
boolean privacyFound = false;
PrivacyConstraint[] privacyConstraints = new PrivacyConstraint[inputs.length];
for ( int i = 0; i < inputs.length; i++ ){
privacyConstraints[i] = getInputPrivacyConstraint(ec, inputs[i]);
if ( privacyConstraints[i] != null )
privacyFound = true;
}
if ( privacyFound )
return privacyConstraints;
}
return null;
}
/**
* Set privacy constraint of data variable with outputName
* if the variable exists and the privacy constraint is not null.
* @param ec execution context from which the data variable is retrieved
* @param privacyConstraint privacy constraint which the variable should have
* @param outputName name of variable that is retrieved from the execution context
*/
private static void setOutputPrivacyConstraint(ExecutionContext ec, PrivacyConstraint privacyConstraint, String outputName){
if ( privacyConstraint != null ){
Data dd = ec.getVariable(outputName);
if ( dd != null ){
dd.setPrivacyConstraints(privacyConstraint);
ec.setVariable(outputName, dd);
}
}
}
public static void postProcessInstruction(Instruction inst, ExecutionContext ec){
// if inst has output
List<CPOperand> instOutputs = getOutputOperands(inst);
if (!instOutputs.isEmpty()){
for ( CPOperand output : instOutputs ){
PrivacyConstraint outputPrivacyConstraint = output.getPrivacyConstraint();
if ( privacyConstraintActivated(outputPrivacyConstraint) )
setOutputPrivacyConstraint(ec, outputPrivacyConstraint, output.getName());
}
}
}
private static boolean privacyConstraintActivated(PrivacyConstraint instructionPrivacyConstraint){
return instructionPrivacyConstraint != null &&
(instructionPrivacyConstraint.privacyLevel == PrivacyLevel.Private
|| instructionPrivacyConstraint.privacyLevel == PrivacyLevel.PrivateAggregation);
}
@SuppressWarnings("unused")
private static String[] getOutputVariableName(Instruction inst){
String[] instructionOutputNames = null;
// The order of the following statements is important
if ( inst instanceof MultiReturnParameterizedBuiltinCPInstruction )
instructionOutputNames = ((MultiReturnParameterizedBuiltinCPInstruction) inst).getOutputNames();
else if ( inst instanceof MultiReturnBuiltinCPInstruction )
instructionOutputNames = ((MultiReturnBuiltinCPInstruction) inst).getOutputNames();
else if ( inst instanceof ComputationCPInstruction )
instructionOutputNames = new String[]{((ComputationCPInstruction) inst).getOutputVariableName()};
else if ( inst instanceof VariableCPInstruction )
instructionOutputNames = new String[]{((VariableCPInstruction) inst).getOutputVariableName()};
else if ( inst instanceof SqlCPInstruction )
instructionOutputNames = new String[]{((SqlCPInstruction) inst).getOutputVariableName()};
return instructionOutputNames;
}
private static List<CPOperand> getOutputOperands(Instruction inst){
// The order of the following statements is important
if ( inst instanceof MultiReturnParameterizedBuiltinCPInstruction )
return ((MultiReturnParameterizedBuiltinCPInstruction) inst).getOutputs();
else if ( inst instanceof MultiReturnBuiltinCPInstruction )
return ((MultiReturnBuiltinCPInstruction) inst).getOutputs();
else if ( inst instanceof ComputationCPInstruction )
return getSingletonList(((ComputationCPInstruction) inst).getOutput());
else if ( inst instanceof VariableCPInstruction )
return getSingletonList(((VariableCPInstruction) inst).getOutput());
else if ( inst instanceof SqlCPInstruction )
return getSingletonList(((SqlCPInstruction) inst).getOutput());
return new ArrayList<>();
}
private static List<CPOperand> getSingletonList(CPOperand operand){
if ( operand != null)
return new ArrayList<>(Collections.singletonList(operand));
return new ArrayList<>();
}
}