BIRT: How to remove a dataset parameter programmatically - java

I want to modify an existing *.rptdesign file and save it under a new name.
The existing file contains a Data Set with a template SQL select statement and several DS parameters.
I'd like to use an actual SQL select statement which uses only part of the DS parameters.
However, the following code results in the exception:
Exception in thread "main" `java.lang.RuntimeException`: *The structure is floating, and its handle is invalid!*
at org.eclipse.birt.report.model.api.StructureHandle.getStringProperty(StructureHandle.java:207)
at org.eclipse.birt.report.model.api.DataSetParameterHandle.getName(DataSetParameterHandle.java:143)
at org.eclipse.birt.report.model.api.DataSetHandle$DataSetParametersPropertyHandle.removeParamBindingsFor(DataSetHandle.java:851)
at org.eclipse.birt.report.model.api.DataSetHandle$DataSetParametersPropertyHandle.removeItems(DataSetHandle.java:694)
--
OdaDataSetHandle dsMaster = (OdaDataSetHandle) report.findDataSet("Master");
HashSet<String> bindVarsUsed = new HashSet<String>();
...
// find out which DS parameters are actually used
HashSet<String> bindVarsUsed = new HashSet<String>();
...
ArrayList<OdaDataSetParameterHandle> toRemove = new ArrayList<OdaDataSetParameterHandle>();
for (Iterator iter = dsMaster.parametersIterator(); iter.hasNext(); ) {
OdaDataSetParameterHandle dsPara = (OdaDataSetParameterHandle)iter.next();
String name = dsPara.getName();
if (name.startsWith("param_")) {
String bindVarName = name.substring(6);
if (!bindVarsUsed.contains(bindVarName)) {
toRemove.add(dsPara);
}
}
}
PropertyHandle paramsHandle = dsMaster.getPropertyHandle( OdaDataSetHandle.PARAMETERS_PROP );
paramsHandle.removeItems(toRemove);
What is wrong here?
Has anyone used the DE API to remove parameters from an existing Data Set?

I had similar issue. Resolved it by calling 'removeItem' multiple times and also had to re-evaluate parametersIterator everytime.
protected void updateDataSetParameters(OdaDataSetHandle dataSetHandle) throws SemanticException {
int countMatches = StringUtils.countMatches(dataSetHandle.getQueryText(), "?");
int paramIndex = 0;
do {
paramIndex = 0;
PropertyHandle odaDataSetParameterProp = dataSetHandle.getPropertyHandle(OdaDataSetHandle.PARAMETERS_PROP);
Iterator parametersIterator = dataSetHandle.parametersIterator();
while(parametersIterator.hasNext()) {
Object next = parametersIterator.next();
paramIndex++;
if(paramIndex > countMatches) {
odaDataSetParameterProp.removeItem(next);
break;
}
}
if(paramIndex < countMatches) {
paramIndex++;
OdaDataSetParameter dataSetParameter = createDataSetParameter(paramIndex);
odaDataSetParameterProp.addItem(dataSetParameter);
}
} while(countMatches != paramIndex);
}
private OdaDataSetParameter createDataSetParameter(int paramIndex) {
OdaDataSetParameter dataSetParameter = StructureFactory.createOdaDataSetParameter();
dataSetParameter.setName("param_" + paramIndex);
dataSetParameter.setDataType(DesignChoiceConstants.PARAM_TYPE_INTEGER);
dataSetParameter.setNativeDataType(1);
dataSetParameter.setPosition(paramIndex);
dataSetParameter.setIsInput(true);
dataSetParameter.setIsOutput(false);
dataSetParameter.setExpressionProperty("defaultValue", new Expression("<evaluation script>", ExpressionType.JAVASCRIPT));
return dataSetParameter;
}

Related

Get number of entries in properties file apache commons

I'm creating a list of IP address' to ping in which a user can add to the list which is then saved to a properties file in the form of site.name1 = ... site.name2 = ...
Currently I have a for loop with a fixed amount, is there a way to get the number of entries in a properties file so I can set this in the for loop rather than wait for a exception?
PropertiesConfiguration config = configs.properties(new File("IPs.properties"));
//initially check for how many values there are - set to max increments for loop
for (int i = 0; i < 3; i++) { //todo fix
siteName = config.getString("site.name" + i);
siteAddress = config.getString("site.address" + i);
SiteList.add(i, siteName);
IPList.add(i, siteAddress);
}
I've looked through the documentation and other questions but they seem to be unrelated.
It looks to me based on the documentation you should be able to use PropertiesConfiguration#getLayout#getKeys to get a Set of all keys as a String.
I had to modify the code a bit to use apache-commons-configuration-1.10
PropertiesConfiguration config = new PropertiesConfiguration("ips.properties");
PropertiesConfigurationLayout layout = config.getLayout();
String siteName = null;
String siteAddress = null;
for (String key : layout.getKeys()) {
String value = config.getString(key);
if (value == null) {
throw new IllegalStateException(String.format("No value found for key: %s", key));
}
if (key.equals("site.name")) {
siteName = value;
} else if (key.equals("site.address")) {
siteAddress = value;
} else {
throw new IllegalStateException(String.format("Unsupported key: %s", key));
}
}
System.out.println(String.format("name=%s, address=%s", siteName, siteAddress));

Make custom code to reduce number of repetitive lines

I have to get 'tags' from the database and store them in an array so I could check if my document contains them. Due to the number of tag categories (customers, system_dependencies, keywords) I have multiple arrays to compare my document with. Is there an easy way to simplify and make my code look nicer?
This is my approach but it looks terrible with all the repetitive for loops.
ArrayList<String> KEYWORDS2 = new ArrayList<String>();
ArrayList<String> CUSTOMERS = new ArrayList<String>();
ArrayList<String> SYSTEM_DEPS = new ArrayList<String>();
ArrayList<String> MODULES = new ArrayList<String>();
ArrayList<String> DRIVE_DEFS = new ArrayList<String>();
ArrayList<String> PROCESS_IDS = new ArrayList<String>();
while (resultSet2.next()) {
CUSTOMERS.add(resultSet2.getString(1));
}
sql = "SELECT da_tag_name FROM da_tags WHERE da_tag_type_id = 6";
stmt = conn.prepareStatement(sql);
resultSet2 = stmt.executeQuery();
while (resultSet2.next()) {
SYSTEM_DEPS.add(resultSet2.getString(1));
}
while (resultSet.next()) {
String da_document_id = resultSet.getString(1);
String file_name = resultSet.getString(2);
try {
if(file_name.endsWith(".docx") || file_name.endsWith(".docm")) {
System.out.println(file_name);
XWPFDocument document = new XWPFDocument(resultSet.getBinaryStream(3));
XWPFWordExtractor wordExtractor = new XWPFWordExtractor(document);
//Return what's inside the document
System.out.println("Keywords found in the document:");
for (String keyword : KEYWORDS) {
if (wordExtractor.getText().contains(keyword)) {
System.out.println(keyword);
}
}
System.out.println("\nCustomers found in the document:");
for (String customer : CUSTOMERS) {
if (wordExtractor.getText().contains(customer)) {
System.out.println(customer);
}
}
System.out.println("\nSystem dependencies found in the document:");
for (String systemDeps : SYSTEM_DEPS) {
if (wordExtractor.getText().contains(systemDeps)) {
System.out.println(systemDeps);
}
}
System.out.println("Log number: " + findLogNumber(wordExtractor));
System.out.println("------------------------------------------");
wordExtractor.close();
}
As you can see there are 3 more to come and this doesn't look good already. Maybe there's a way to compare all of them at the same time.
I have made another attempt at this creating this method:
public void genericForEachLoop(ArrayList<String> al, POITextExtractor te) {
for (String item : al) {
if (te.getText().contains(item)) {
System.out.println(item);
}
}
}
Then calling it like so: genericForEachLoop(MODULES, wordExtractor);
Any better solutions?
I've got two ideas to shorten this: first of all you can write a general for-loop in a separate method that has an ArrayList as a parameter. Then you pass it each of your ArrayLists successively, which would mean that at least you do not have to repeat the for-loops. Secondly, you can create an ArrayList of type ArrayList and store your ArrayLists inside it. Then you can iterate over the whole thing. Only apparent disadvantage of both ideas (or a combination of them) would be, that you need to name the variable for your query string alike for the search of each ArrayList.
What you could do is use a Map and an enum like this:
enum TagType {
KEYWORDS2(2), // or whatever its da_tag_type_id is
CUSTOMERS(4),
SYSTEM_DEPS(6),
MODULES(8),
DRIVE_DEFS(10),
PROCESS_IDS(12);
public final daTagTypeId; // this will be used in queries
TagType(int daTagTypeId) {
this.daTagTypeId = daTagTypeId;
}
}
Map<TagType, List<String>> tags = new HashMap<>();
XWPFDocument document = new XWPFDocument(resultSet.getBinaryStream(3));
XWPFWordExtractor wordExtractor = new XWPFWordExtractor(document);
for(TagType tagType : TagType.values()) {
tags.put(tagType, new ArrayList<>()); // initialize
String sql = String.format("SELECT da_tag_name FROM da_tags WHERE da_tag_type_id = %d", tagType.daTagTypeId); // build query
stmt = conn.prepareStatement(sql);
resultSet2 = stmt.executeQuery();
while(resultSet2.next()) { // fill from DB
tags.get(tagType).add(.add(resultSet2.getString(1)));
}
System.out.println(String.format("%s found in the document:", tags.get(tagType).name());
for (String tag : tags.get(tagType)) { // search in text
if (wordExtractor.getText().contains(tag)) {
System.out.println(keyword);
}
}
}
But at this point I'm not sure you need those lists at all:
enum TagType {
KEYWORDS2(2), // or whatever its da_tag_type_id is
CUSTOMERS(4),
SYSTEM_DEPS(6),
MODULES(8),
DRIVE_DEFS(10),
PROCESS_IDS(12);
public final daTagTypeId; // this will be used in queries
TagType(int daTagTypeId) {
this.daTagTypeId = daTagTypeId;
}
}
XWPFDocument document = new XWPFDocument(resultSet.getBinaryStream(3));
XWPFWordExtractor wordExtractor = new XWPFWordExtractor(document);
for(TagType tagType : TagType.values()) {
String sql = String.format("SELECT da_tag_name FROM da_tags WHERE da_tag_type_id = %d", tagType.daTagTypeId); // build query
stmt = conn.prepareStatement(sql);
resultSet2 = stmt.executeQuery();
System.out.println(String.format("%s found in the document:", tags.get(tagType).name());
while(result2.next()) {
String tag = resultSet2.getString(1);
if (wordExtractor.getText().contains(tag)) {
System.out.println(keyword);
}
}
}
This given I don't know where those resultSet is declared and initialised, nor where that resultSet2 is initialised.
Basically you just fetch tags for each type from DB and then directly search them in the text without storing them at first and then re-iterating the stored ones... I mean that's what the DB is there for.

String cannot be added to List using Object in Java

I am working on a JSF based Web Application where I read contents from a file(dumpfile) and then parse it using a logic and keep adding it to a list using an object and also set a string using the object. But I keep getting this error. I am confused where I am wrong. I am a beginner so can anyone be kind enough to help me?
List<DumpController> FinalDumpNotes;
public List<DumpController> initializeDumpNotes()
throws SocketException, IOException {
PostProcessedDump postProcessedDump = (PostProcessedDump) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("postProcessedDump");
List<DumpController> FinalNotes = new ArrayList<>();
if (postProcessedDump.getDumpNotes() == null) {
dumpNotes = new DumpNotes();
}
DumpListController dlcon = (DumpListController) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("dumpListController");
DumpInfo dumpinfo = dlcon.getSelectedDumpInfo();
String fileName = dumpinfo.getDate() + dumpinfo.getTime() + dumpinfo.getSeqNo() + dumpinfo.getType() + dumpinfo.getTape() + dumpinfo.getDescription() + ".txt";
if (checkFileExistsInWin(fileName)) {
postProcessedDump.setDumpnotescontent(getFileContentsFromWin(fileName));
String consolidateDumpnotes = getFileContentsFromWin(fileName);
String lines[];
String content = "";
lines = consolidateDumpnotes.split("\\r?\\n");
List<String> finallines = new ArrayList<>();
int k = 0;
for (int i = 0; i < lines.length; i++) {
if (!lines[i].equalsIgnoreCase("")) {
finallines.add(lines[i]);
k++;
}
}
for (int j = 0; j < finallines.size(); j++) {
if (finallines.get(j).startsWith("---------------------SAVED BY")) {
PostProcessedDump dump = new PostProcessedDump();
dump.setDumpMessage(content);
content = "";
FinalDumpNotes.add(dump);
} else {
content = content + finallines.get(j);
}
}
}
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("postProcessedDump", postProcessedDump);
return FinalDumpNotes;
}
I get the following error:
If you want to add instances of type PostProcessedDump to your List you should change it's type. Also, don't forget to initialize it. Something like,
List<PostProcessedDump> FinalDumpNotes = new ArrayList<>();
Also, Java naming convention is to start variable names with a lower case letter. FinalDumpNotes looks like a class, I would suggest something like
List<PostProcessedDump> processedList = new ArrayList<>();
Problems with your code:
List<DumpController> FinalDumpNotes;
You declare FinalDumpNotes to be a List of DumpController objects, but you never initialize it. In addition, your IDE is barfing on the following line of code:
FinalDumpNotes.add(dump);
because you are attempting to add a PostProcessedDump object to the List instead of a DumpController object.
For starters, you need to initialize your list like this:
List<DumpController> finalDumpNotes = new ArrayList<DumpController>();
Notice that I have made the variable name beginning with lower case, which is the convention (upper case is normally reserved for classes and interfaces).
I will leave it to you as a homework assignment to sort out the correct usage of this List.

set Exampleset to ExampleSet2SimilarityExampleSet Rapidminer Operator with java

I create a process that measure similarity. I use ExampleSet2SimilarityExampleSetoperator and I want to add in input an example set which generated in my code.
The first idea is to write my example set in local repository. Then I will use retrieve operator to read example set and connect the output of operator retrieve to input of operator ExampleSet2SimilarityExampleSet.
So I wonder if I can avoid read/write.
public class Test {
public static void main(String[] args) throws OperatorCreationException, OperatorException{
Test t = new Test();
t.createprocess();
}
public void createprocess() throws OperatorCreationException, OperatorException{
RapidMiner.init();
ExampleSet exampleset = getExampleset();
Operator silimarityOperator = OperatorService.createOperator(ExampleSet2SimilarityExampleSet.class);
// silimarityOperator.setParameter("measure_type", "NumericalMeasures");
// silimarityOperator.setParameter("numerical_measure", "CosineSimilarity");
Process process = new Process();
process.getRootOperator().getSubprocess(0).addOperator(silimarityOperator);
process.getRootOperator().getSubprocess(0).getInnerSources().getPortByIndex(0).connectTo( silimarityOperator.getInputPorts().getPortByName("input"));
// run the process with new IOContainer using the created exampleSet
IOContainer run = process.run(new IOContainer(exampleset));
System.out.println(run.toString());
}
public ExampleSet getExampleset() {
// construct attribute set
Attribute[] attributes = new Attribute[3];
attributes[0] = AttributeFactory.createAttribute("Topic1", Ontology.STRING);
attributes[1] = AttributeFactory.createAttribute("Topic2", Ontology.STRING);
attributes[2] = AttributeFactory.createAttribute("Topic3", Ontology.STRING);
MemoryExampleTable table = new MemoryExampleTable(attributes);
DataRowFactory ROW_FACTORY = new DataRowFactory(0);
Double[] strings = new Double[3];
double a = 0;
for (int i = 0; i < 3; i++) {
a++;
strings[i] = a;
// make and add row
DataRow row = ROW_FACTORY.create(strings, attributes);
table.addDataRow(row);
}
ExampleSet exampleSet = table.createExampleSet();
return exampleSet;
}
}
I found solution. I have error at connection of operator. It is not exist port input, so I get port 0.
process.getRootOperator().getSubprocess(0).getInnerSources().getPortByIndex(0).connectTo(
silimarityOperator.getInputPorts().getPortByIndex(0));
silimarityOperator.getOutputPorts().getPortByIndex(0).connectTo(
process.getRootOperator().getSubprocess(0).getInnerSinks().getPortByIndex(0));

Iterating over lists using multiple threads

Following code(part shown) creates objects of class DescCalculator and calculate descriptors and returns them as string arrays. A molecule and a ArrayList of Descriptor objects are passed in.
private void calcDesc()
{
try
{
StatusPanel.setStatus("Calculating Molecular Descriptors Using CDK...\n");
File df = new File(Settings.getCurrentDirectory() + sep + "molDesc.csv");
FileWriter dfw = new FileWriter(df);
LoadSDF lsdf1 = new LoadSDF(Settings.getCurrentDirectory() + sep + "marvin3D.sdf");
List<IAtomContainer> mols3D = lsdf1.getCompounds();
DescriptorEngine engine = new DescriptorEngine(DescriptorEngine.MOLECULAR);
List<String> classNames = engine.getDescriptorClassNames();
List<String> removeList = new ArrayList();
removeList.add("org.openscience.cdk.qsar.descriptors.molecular.IPMolecularLearningDescriptor");
classNames.removeAll(removeList);
List<IDescriptor> instances = engine.instantiateDescriptors(classNames);
engine.setDescriptorInstances(instances);
List<String> headerItems = new ArrayList<String>();
headerItems.add("CID");
headerItems.add("MobCSA");
for (IDescriptor descriptor : instances) {
String[] names = descriptor.getDescriptorNames();
headerItems.addAll(Arrays.asList(names));
}
ArrayList<IMolecularDescriptor> descriptors = new ArrayList();
for (Object object : instances)
{
IMolecularDescriptor descriptor = (IMolecularDescriptor) object;
String[] comps = descriptor.getSpecification().getSpecificationReference().split("#");
descriptors.add(descriptor);
}
String headerLine = "";
for (String header : headerItems) {
headerLine = headerLine + header + ",";
}
dfw.append(headerLine+"\n");
ExecutorService eservice = Executors.newFixedThreadPool(threads);
CompletionService <List<String>> cservice = new ExecutorCompletionService <List<String>> (eservice);
int k=0;
for (IAtomContainer mol : mols3D)
{
DescCalculator dc = new DescCalculator(mol,descriptors);
cservice.submit(dc);
k=k+1;
}
for (int j=1 ; j<=k; j++)
{
StatusPanel.setStatus("Calculating Descriptors for Molecule "+j+"/"+compounds.size()+" Using "+threads+" Processors\n");
List<String> dataItems = cservice.take().get();
for (int i = 0; i < dataItems.size(); i++) {
if (dataItems.get(i).equals("NaN")) {
dataItems.set(i, "NA");
}
}
try {
String dataLine = "";
for (String data : dataItems) {
dataLine = dataLine + data + ",";
}
dfw.append(dataLine+"\n");
} catch (Exception e) {
System.out.println(e.toString());
}
}
dfw.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Inside the class there is a for loop that goes over the list of descriptors as follows (part shown). This code runs into concurrent modification exception. If I use threads=1 or descriptor iteration inside a synchronized{} block the code runs fine but i don't get the parallellization needed.How do I iterate over the list inside class DesCalculator ??
public class DescCalculator implements Callable<List<String>>{
private IAtomContainer mol = new Molecule();
private ArrayList<IMolecularDescriptor> molDesc;
DescCalculator(IAtomContainer mol_, ArrayList<IMolecularDescriptor> molDesc_)
{
this.mol = mol_;
this.molDesc = molDesc_;
}
#Override
public List<String> call() {
List<String> dataItems = new ArrayList<String>();
try
{
String title = (String) mol.getProperty("PUBCHEM_COMPOUND_CID");
dataItems.add(title);
//String csa = Double.toString(mobcalCSA.get(ind));
String csa = "NA";
dataItems.add(csa);
int ndesc = 0;
for (IMolecularDescriptor descriptor : molDesc) {
descriptor.calculate(mol);
DescriptorValue value = descriptor.calculate(mol);
if (value.getException() != null) {
for (int i = 0; i < value.getNames().length; i++) {
dataItems.add("NA");
}
continue;
}
IDescriptorResult result = value.getValue();
if (result instanceof DoubleResult) {
dataItems.add(String.valueOf(((DoubleResult) result).doubleValue()));
} else if (result instanceof IntegerResult) {
dataItems.add(String.valueOf(((IntegerResult) result).intValue()));
} else if (result instanceof DoubleArrayResult) {
for (int i = 0; i < ((DoubleArrayResult) result).length(); i++) {
dataItems.add(String.valueOf(((DoubleArrayResult) result).get(i)));
}
} else if (result instanceof IntegerArrayResult) {
for (int i = 0; i < ((IntegerArrayResult) result).length(); i++) {
dataItems.add(String.valueOf(((IntegerArrayResult) result).get(i)));
}
}
ndesc++;
}
}
catch(Exception e)
{
e.printStackTrace();
}
return dataItems;
}
}
Print Stack Trace
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at org.openscience.cdk.ChemObject.notifyChanged(ChemObject.java:187)
at org.openscience.cdk.ChemObject.setFlag(ChemObject.java:375)
at org.openscience.cdk.graph.PathTools.depthFirstTargetSearch(PathTools.java:168)
at org.openscience.cdk.graph.PathTools.depthFirstTargetSearch(PathTools.java:177)
at org.openscience.cdk.graph.PathTools.depthFirstTargetSearch(PathTools.java:177)
at org.openscience.cdk.graph.SpanningTree.getRing(SpanningTree.java:185)
at org.openscience.cdk.graph.SpanningTree.getCyclicFragmentsContainer(SpanningTree.java:221)
at org.openscience.cdk.atomtype.CDKAtomTypeMatcher.getRing(CDKAtomTypeMatcher.java:912)
at org.openscience.cdk.atomtype.CDKAtomTypeMatcher.perceiveNitrogens(CDKAtomTypeMatcher.java:730)
at org.openscience.cdk.atomtype.CDKAtomTypeMatcher.findMatchingAtomType(CDKAtomTypeMatcher.java:117)
at org.openscience.cdk.tools.manipulator.AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(AtomContainerManipulator.java:719)
at org.openscience.cdk.smiles.smarts.SMARTSQueryTool.initializeMolecule(SMARTSQueryTool.java:435)
at org.openscience.cdk.smiles.smarts.SMARTSQueryTool.matches(SMARTSQueryTool.java:214)
at org.openscience.cdk.smiles.smarts.SMARTSQueryTool.matches(SMARTSQueryTool.java:189)
at org.openscience.cdk.qsar.descriptors.molecular.AcidicGroupCountDescriptor.calculate(AcidicGroupCountDescriptor.java:135)
at edu.uconn.pharmacy.molfind.DescCalculator.call(DescCalculator.java:48)
at edu.uconn.pharmacy.molfind.DescCalculator.call(DescCalculator.java:25)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
You should not get the exception unless you are actually modifying a Collection at the same time you are walking across it. Often this can be done in 1 thread by doing a delete from a Collection you are iterating across -- in a for for example.
But in your case I guess you are removing from molDesc list somewhere although I can't see that in the code sample you provided. If you need to remove entries from the list then you will have to use some other mechanism to do the deletes. You cannot alter the same collection in multiple threads unless it is somehow synchronized.
Couple other ideas:
Now sure if it needs to be the exact same list. You could have each thread work with a copy of the list.
DescCalculator dc =
new DescCalculator(mol, new ArrayList<IMolecularDescriptor>(descriptors));
You could just pass in a Collections.synchronizedList copy of molDesc although I'm not sure that's what you want.
List<IMolecularDescriptor> syncedList =
Collections.synchronizedList(descriptors);
...
DescCalculator dc = new DescCalculator(mol, syncedList);
Each thread could keep a list of items that need to be deleted. At the end you could use the Future when the thread is reaped to get the deleted list of items and remove them from the list at the end.
Your molDesc field is shared state between 2 or more threads that access the call() method. As you stated, the only way to avoid the CMEs is to wrap the iteration in a synchronized() block (which will prevent you from parallelizing), or use a threadsafe structure like CopyOnWriteArrayList as Victor mentioned.
It turns out the problem is with descriptor objects which are not thread safe. I thank Affe for pointing it out ! Generating them inside DescCalculator class fixed the problem. I thank everyone for their input !

Categories