1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under
4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution,
5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html
6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: ReportDataModel.java,v 1.1.1.1 2004/05/09 16:57:38 vlad_r Exp $
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.report;
10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.HashMap;
12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Iterator;
13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Map;
14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Descriptors;
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert;
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppErrorCodes;
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMARuntimeException;
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.ClassDescriptor;
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.IMetaData;
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.IMetadataConstants;
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.ICoverageData;
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.MethodDescriptor;
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/**
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class ReportDataModel implements IReportDataModel
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // public: ................................................................
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public synchronized IReportDataView getView (final int viewType)
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // TODO: merge the two branches together
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (viewType >= m_views.length) throw new IllegalArgumentException ("invalid viewType: " + viewType);
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        IReportDataView view = m_views [viewType];
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (view != null)
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return view;
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final boolean srcView = viewType == IReportDataView.HIER_SRC_VIEW;
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (srcView && ! m_mdata.hasSrcFileData ())
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new IllegalStateException ("source file data view requested for metadata with incomplete SourceFile debug info");
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final AllItem root = new AllItem ();
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final Map /* String(pkg name) -> PackageItem */ packageMap = new HashMap ();
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final Map /* String(pkg-prefixed src file name) -> ClassItem */ srcfileMap = new HashMap ();
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (Iterator /* ClassDescriptor */ descriptors = m_mdata.iterator (); descriptors.hasNext (); )
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final ClassDescriptor cls = (ClassDescriptor) descriptors.next ();
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                String packageVMName = cls.getPackageVMName ();
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                PackageItem packageItem = (PackageItem) packageMap.get (packageVMName);
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (packageItem == null)
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final String packageName = packageVMName.length () == 0 ? "default package" : Descriptors.vmNameToJavaName (packageVMName);
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    packageItem = new PackageItem (root, packageName, packageVMName);
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    packageMap.put (packageVMName, packageItem);
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    root.addChild (packageItem);
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                SrcFileItem srcfileItem = null;
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (srcView)
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final String srcFileName = cls.getSrcFileName ();
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ($assert.ENABLED) $assert.ASSERT (srcFileName != null, "src file name = null");
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final String fullSrcFileName = Descriptors.combineVMName (packageVMName, srcFileName);
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    srcfileItem = (SrcFileItem) srcfileMap.get (fullSrcFileName);
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (srcfileItem == null)
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        srcfileItem = new SrcFileItem (packageItem, srcFileName, fullSrcFileName);
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        srcfileMap.put (fullSrcFileName, srcfileItem);
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        packageItem.addChild (srcfileItem);
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final ICoverageData.DataHolder data = m_cdata.getCoverage (cls);
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // check metadata and coverage data consistency:
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (data != null)
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (data.m_stamp != cls.getStamp ())
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw new EMMARuntimeException (IAppErrorCodes.CLASS_STAMP_MISMATCH,
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                                                        new Object [] { Descriptors.vmNameToJavaName (cls.getClassVMName ()) });
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final boolean [][] coverage = data != null ? data.m_coverage : null;
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if ($assert.ENABLED) $assert.ASSERT (! srcView || srcfileItem != null, "null srcfileItem");
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final ClassItem classItem = srcView ? new ClassItem (srcfileItem, cls, coverage) : new ClassItem (packageItem, cls, coverage);
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final MethodDescriptor [] methods = cls.getMethods ();
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // TODO: handle edge case when all methods of a class have METHOD_NO_BLOCK_DATA set
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                for (int m = 0; m < methods.length; ++ m)
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final MethodDescriptor method = methods [m];
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ((method.getStatus () & IMetadataConstants.METHOD_NO_BLOCK_DATA) != 0) continue;
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // TODO: wouldn't it be more consistent to simply pass the entire descriptor into MethodItems? (eval mem savings)
114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final MethodItem methodItem = new MethodItem (classItem, m, method.getName (), method.getDescriptor (), method.getFirstLine ());
115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // TODO: need to fold class's name into a method name prefix for collapsing case [only when it is not the same as the file name]
116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    classItem.addChild (methodItem);
118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (srcView)
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    srcfileItem.addChild (classItem);
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    packageItem.addChild (classItem);
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            view = new ReportDataView (root);
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_views [viewType] = view;
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return view;
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // protected: .............................................................
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // package: ...............................................................
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    ReportDataModel (final IMetaData mdata, final ICoverageData cdata)
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (mdata == null) throw new IllegalArgumentException ("null input: mdata");
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (cdata == null) throw new IllegalArgumentException ("null input: cdata");
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_views = new IReportDataView [2];
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // TODO: report generators work off data model views only; I should deref
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // mdata and cdata as soon as all possible views have been constructed and cached
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_mdata = mdata;
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_cdata = cdata;
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // private: ...............................................................
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class ReportDataView implements IReportDataView
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        public IItem getRoot()
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return m_root;
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        ReportDataView (final IItem root)
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_root = root;
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        private final IItem m_root;
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IMetaData m_mdata;
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final ICoverageData m_cdata;
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IReportDataView [] m_views;
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------