/*
* This is a prototype implementation of the concept of Feature-Sen
* sitive Dataflow Analysis. More details in the AOSD'12 paper:
* Dataflow Analysis for Software Product Lines
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package br.ufal.cideei.soot.analyses;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import soot.toolkits.scalar.AbstractFlowSet;
import soot.toolkits.scalar.ArraySparseSet;
import soot.toolkits.scalar.FlowSet;
import br.ufal.cideei.soot.instrument.IConfigRep;
/**
* The Class LiftedFlowSet.
*
* @param <T>
* the generic type
*/
//XXX refatorar!
public class LiftedFlowSet extends AbstractFlowSet {
private int liftedFlowSetSize;
private IConfigRep[] configurations;
private FlowSet[] lattices;
/**
* Instantiates a new LiftedFlowSet.
*/
public LiftedFlowSet(Collection<IConfigRep> configs) {
this.liftedFlowSetSize = configs.size();
// Both lists have the same size...
// Configurations = [ {}, {A}, {B}, {A, B} ]
// Lattices = [ l1, l2, l3, l4 ]
this.configurations = new IConfigRep[liftedFlowSetSize];
this.lattices = new FlowSet[liftedFlowSetSize];
// Ugly... configs does not have a get method... :-(
int i = 0;
for (IConfigRep configuration : configs) {
this.configurations[i] = configuration;
this.lattices[i] = new ArraySparseSet();
i++;
}
}
/**
* Instantiates a new LiftedFlowSet, but copy the contents of the other into
* this. A pseudo copy-constructor.
*
* @param other
* the other
*/
public LiftedFlowSet(LiftedFlowSet other) {
this.configurations = other.configurations.clone();
this.lattices = other.lattices.clone();
this.liftedFlowSetSize = other.liftedFlowSetSize;
}
private LiftedFlowSet() {
}
/**
* @return the configurations of this lifted lattice.
*/
public IConfigRep[] getConfigurations() {
return configurations;
}
/**
* @return the normal lattices contained in this lifted lattice.
*/
public FlowSet[] getLattices() {
return lattices;
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#clone()
*/
@Override
public LiftedFlowSet clone() {
LiftedFlowSet other = new LiftedFlowSet();
other.configurations = this.configurations.clone();
other.lattices = new FlowSet[this.lattices.length];
for (int index = 0; index < lattices.length; index++) {
other.lattices[index] = this.lattices[index].clone();
}
other.liftedFlowSetSize = this.liftedFlowSetSize;
return other;
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
// A LiftedFlowSet can only be equal to another LiftedFlowSet
if (!(obj instanceof LiftedFlowSet))
return false;
// Test for self-equality
if (obj == this)
return true;
LiftedFlowSet other = (LiftedFlowSet) obj;
// Deep-check equality
boolean returnFlag = true;
for (int i = 0; i < liftedFlowSetSize; i++) {
if (!other.configurations[i].equals(this.configurations[i]) || !other.lattices[i].equals(this.lattices[i])) {
returnFlag = false;
break;
}
}
return returnFlag;
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#clear()
*/
@Override
public void clear() {
this.configurations = null;
this.lattices = null;
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#add(java.lang.Object)
*/
@Override
public void add(Object object) {
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#contains(java.lang.Object)
*/
@Override
public boolean contains(Object object) {
throw new UnsupportedOperationException("This method is not defined for a LiftedFlowSet");
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#isEmpty()
*/
@Override
public boolean isEmpty() {
return ((configurations.length == 0) && (lattices.length == 0));
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#remove(java.lang.Object)
*/
@Override
public void remove(Object object) {
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#size()
*/
@Override
public int size() {
return this.liftedFlowSetSize;
}
/*
* (non-Javadoc)
*
* @see soot.toolkits.scalar.AbstractFlowSet#toList()
*/
@Override
public List toList() {
throw new UnsupportedOperationException("This method is not defined for a LiftedFlowSet");
}
/**
* Copies this Config-FlowSet mapping into dest.
*
* @see soot.toolkits.scalar.AbstractFlowSet#copy(soot.toolkits.scalar.FlowSet)
*/
@Override
public void copy(FlowSet dest) {
LiftedFlowSet destLifted = (LiftedFlowSet) dest;
for (int i = 0; i < this.liftedFlowSetSize; i++) {
FlowSet destNormal = (FlowSet) destLifted.lattices[i];
FlowSet thisNormal = (FlowSet) lattices[i];
thisNormal.copy(destNormal);
}
}
/**
* The union between LiftedFlowSets is defined as the union between every
* FlowSets in @code{this} and the FlowSets in @code{other} with the same
* configuration.
*
* The result is placed on @code{dest}. It`s keys are preserved, but its
* flowsets are cleared.
*
* @see soot.toolkits.scalar.AbstractFlowSet#union(soot.toolkits.scalar.FlowSet,
* soot.toolkits.scalar.FlowSet)
*/
@Override
public void union(FlowSet other, FlowSet dest) {
LiftedFlowSet otherLifted = (LiftedFlowSet) other;
LiftedFlowSet destLifted = (LiftedFlowSet) dest;
for (int i = 0; i < this.liftedFlowSetSize; i++) {
FlowSet otherNormal = (FlowSet) otherLifted.lattices[i];
FlowSet thisNormal = (FlowSet) lattices[i];
FlowSet destNewFlowSet = new ArraySparseSet();
destLifted.lattices[i] = destNewFlowSet;
thisNormal.union(otherNormal, destNewFlowSet);
}
}
/**
* Returns a String representation of this object.
*
* @return String representation
*
*/
@Override
public String toString() {
StringBuffer result = new StringBuffer();
for (int i = 0; i < this.liftedFlowSetSize; i++) {
result.append(this.configurations[i].toString());
result.append("=");
result.append(this.lattices[i].toString());
result.append("; ");
}
return result.toString();
}
}