| /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under |
| * the terms of the Common Public License v1.0 which accompanies this distribution, |
| * and is available at http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * $Id: CoverageData.java,v 1.1.1.1 2004/05/09 16:57:31 vlad_r Exp $ |
| */ |
| package com.vladium.emma.data; |
| |
| import java.io.DataInput; |
| import java.io.DataOutput; |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import com.vladium.util.asserts.$assert; |
| |
| // ---------------------------------------------------------------------------- |
| /** |
| * @author Vlad Roubtsov, (C) 2003 |
| */ |
| final class CoverageData implements ICoverageData, Cloneable |
| { |
| // public: ................................................................ |
| |
| // TODO: duplicate issue |
| |
| public Object lock () |
| { |
| return m_coverageMap; |
| } |
| |
| public ICoverageData shallowCopy () |
| { |
| final CoverageData _clone; |
| try |
| { |
| _clone = (CoverageData) super.clone (); |
| } |
| catch (CloneNotSupportedException cnse) |
| { |
| throw new Error (cnse.toString ()); |
| } |
| |
| final HashMap _coverageMap; |
| |
| synchronized (lock ()) |
| { |
| _coverageMap = (HashMap) m_coverageMap.clone (); |
| } |
| |
| _clone.m_coverageMap = _coverageMap; |
| |
| return _clone; |
| } |
| |
| public int size () |
| { |
| return m_coverageMap.size (); |
| } |
| |
| public DataHolder getCoverage (final ClassDescriptor cls) |
| { |
| if (cls == null) throw new IllegalArgumentException ("null input: cls"); |
| |
| return (DataHolder) m_coverageMap.get (cls.getClassVMName ()); |
| } |
| |
| public void addClass (final boolean [][] coverage, final String classVMName, final long stamp) |
| { |
| m_coverageMap.put (classVMName, new DataHolder (coverage, stamp)); |
| } |
| |
| // IMergeable: |
| |
| public boolean isEmpty () |
| { |
| return m_coverageMap.isEmpty (); |
| } |
| |
| /* |
| * This method is not MT-safe wrt addClass() etc. |
| * |
| * note: rhs entries override current entries if they have different stamps; |
| * otherwise, the data is merged |
| */ |
| public IMergeable merge (final IMergeable rhs) |
| { |
| if ((rhs == null) || rhs.isEmpty () || (rhs == this)) |
| return this; |
| else |
| { |
| final CoverageData rhscdata = (CoverageData) rhs; // TODO: redesign so that the cast is not necessary |
| final Map rhscoverageData = rhscdata.m_coverageMap; |
| |
| for (Iterator entries = rhscoverageData.entrySet ().iterator (); entries.hasNext (); ) |
| { |
| final Map.Entry entry = (Map.Entry) entries.next (); |
| final String classVMName = (String) entry.getKey (); |
| |
| final DataHolder rhsdata = (DataHolder) entry.getValue (); |
| // [assertion: rhsdata != null] |
| |
| final DataHolder data = (DataHolder) m_coverageMap.get (classVMName); |
| |
| if (data == null) |
| m_coverageMap.put (classVMName, rhsdata); |
| else |
| { |
| if (rhsdata.m_stamp != data.m_stamp) |
| m_coverageMap.put (classVMName, rhsdata); |
| else // merge two runtime profiles |
| { |
| final boolean [][] rhscoverage = rhsdata.m_coverage; |
| final boolean [][] coverage = data.m_coverage; |
| |
| // [assertion: both coverage and rhscoverage aren't null] |
| |
| if ($assert.ENABLED) $assert.ASSERT (coverage.length == rhscoverage.length, "coverage.length [" + coverage.length + "] != rhscoverage.length [" + rhscoverage.length + "]"); |
| for (int m = 0, mLimit = coverage.length; m < mLimit; ++ m) |
| { |
| final boolean [] rhsmcoverage = rhscoverage [m]; |
| final boolean [] mcoverage = coverage [m]; |
| |
| if (mcoverage == null) |
| { |
| if ($assert.ENABLED) $assert.ASSERT (rhsmcoverage == null, "mcoverage == null but rhsmcoverage != null"); |
| |
| // [nothing to merge] |
| } |
| else |
| { |
| if ($assert.ENABLED) $assert.ASSERT (rhsmcoverage != null, "mcoverage != null but rhsmcoverage == null"); |
| if ($assert.ENABLED) $assert.ASSERT (mcoverage.length == rhsmcoverage.length, "mcoverage.length [" + mcoverage.length + "] != rhsmcoverage.length [" + rhsmcoverage.length + "]"); |
| |
| for (int b = 0, bLimit = mcoverage.length; b < bLimit; ++ b) |
| { |
| if (rhsmcoverage [b]) mcoverage [b] = true; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| return this; |
| } |
| } |
| |
| // protected: ............................................................. |
| |
| // package: ............................................................... |
| |
| |
| CoverageData () |
| { |
| m_coverageMap = new HashMap (); |
| } |
| |
| |
| static CoverageData readExternal (final DataInput in) |
| throws IOException |
| { |
| final int size = in.readInt (); |
| final HashMap coverageMap = new HashMap (size); |
| |
| for (int i = 0; i < size; ++ i) |
| { |
| final String classVMName = in.readUTF (); |
| final long stamp = in.readLong (); |
| |
| final int length = in.readInt (); |
| final boolean [][] coverage = new boolean [length][]; |
| for (int c = 0; c < length; ++ c) |
| { |
| coverage [c] = DataFactory.readBooleanArray (in); |
| } |
| |
| coverageMap.put (classVMName, new DataHolder (coverage, stamp)); |
| } |
| |
| return new CoverageData (coverageMap); |
| } |
| |
| static void writeExternal (final CoverageData cdata, final DataOutput out) |
| throws IOException |
| { |
| final Map coverageMap = cdata.m_coverageMap; |
| |
| final int size = coverageMap.size (); |
| out.writeInt (size); |
| |
| final Iterator entries = coverageMap.entrySet ().iterator (); |
| for (int i = 0; i < size; ++ i) |
| { |
| final Map.Entry entry = (Map.Entry) entries.next (); |
| |
| final String classVMName = (String) entry.getKey (); |
| final DataHolder data = (DataHolder) entry.getValue (); |
| |
| final boolean [][] coverage = data.m_coverage; |
| |
| out.writeUTF (classVMName); |
| out.writeLong (data.m_stamp); |
| |
| final int length = coverage.length; |
| out.writeInt (length); |
| for (int c = 0; c < length; ++ c) |
| { |
| DataFactory.writeBooleanArray (coverage [c], out); |
| } |
| } |
| } |
| |
| // private: ............................................................... |
| |
| |
| private CoverageData (final HashMap coverageMap) |
| { |
| if ($assert.ENABLED) $assert.ASSERT (coverageMap != null, "coverageMap is null"); |
| m_coverageMap = coverageMap; |
| } |
| |
| |
| private /*final*/ HashMap /* String(classVMName) -> DataHolder */ m_coverageMap; // never null |
| |
| } // end of class |
| // ---------------------------------------------------------------------------- |