001/*
002 * Cobertura - http://cobertura.sourceforge.net/
003 *
004 * Copyright (C) 2003 jcoverage ltd.
005 * Copyright (C) 2005 Mark Doliner
006 * Copyright (C) 2005 Jeremy Thomerson
007 *
008 * Cobertura is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License as published
010 * by the Free Software Foundation; either version 2 of the License,
011 * or (at your option) any later version.
012 *
013 * Cobertura is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016 * General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with Cobertura; if not, write to the Free Software
020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
021 * USA
022 */
023
024package net.sourceforge.cobertura.coveragedata;
025
026import java.util.Collection;
027import java.util.Iterator;
028import java.util.SortedMap;
029import java.util.SortedSet;
030import java.util.TreeMap;
031import java.util.TreeSet;
032
033public class PackageData extends CoverageDataContainer
034                implements Comparable, HasBeenInstrumented
035{
036
037        private static final long serialVersionUID = 7;
038
039        private String name;
040
041        public PackageData(String name)
042        {
043                if (name == null)
044                        throw new IllegalArgumentException(
045                                        "Package name must be specified.");
046                this.name = name;
047        }
048    
049        public void addClassData(ClassData classData)
050        {
051                lock.lock();
052                try
053                {
054                        if (children.containsKey(classData.getBaseName()))
055                                throw new IllegalArgumentException("Package " + this.name
056                                                + " already contains a class with the name "
057                                                + classData.getBaseName());
058        
059                        // Each key is a class basename, stored as an String object.
060                        // Each value is information about the class, stored as a ClassData object.
061                        children.put(classData.getBaseName(), classData);
062                }
063                finally
064                {
065                        lock.unlock();
066                }
067        }
068
069        /**
070         * This is required because we implement Comparable.
071         */
072        public int compareTo(Object o)
073        {
074                if (!o.getClass().equals(PackageData.class))
075                        return Integer.MAX_VALUE;
076                return this.name.compareTo(((PackageData)o).name);
077        }
078
079        public boolean contains(String name)
080        {
081                lock.lock();
082                try
083                {
084                        return this.children.containsKey(name);
085                }
086                finally
087                {
088                        lock.unlock();
089                }
090        }
091
092        /**
093         * Returns true if the given object is an instance of the
094         * PackageData class, and it contains the same data as this
095         * class.
096         */
097        public boolean equals(Object obj)
098        {
099                if (this == obj)
100                        return true;
101                if ((obj == null) || !(obj.getClass().equals(this.getClass())))
102                        return false;
103
104                PackageData packageData = (PackageData)obj;
105                getBothLocks(packageData);
106                try
107                {
108                        return super.equals(obj) && this.name.equals(packageData.name);
109                }
110                finally
111                {
112                        lock.unlock();
113                        packageData.lock.unlock();
114                }
115        }
116
117        public SortedSet getClasses()
118        {
119                lock.lock();
120                try
121                {
122                        return new TreeSet(this.children.values());
123                }
124                finally
125                {
126                        lock.unlock();
127                }
128        }
129
130        public String getName()
131        {
132                return this.name;
133        }
134
135        public String getSourceFileName()
136        {
137                return this.name.replace('.', '/');
138        }
139
140        public Collection getSourceFiles()
141        {
142                SortedMap sourceFileDatas = new TreeMap();
143                
144                lock.lock();
145                try
146                {
147                        Iterator iter = this.children.values().iterator();
148                        while (iter.hasNext()) {
149                                ClassData classData = (ClassData)iter.next();
150                                String sourceFileName = classData.getSourceFileName();
151                                SourceFileData sourceFileData = (SourceFileData)sourceFileDatas.get(sourceFileName);
152                                if (sourceFileData == null)
153                                {
154                                        sourceFileData = new SourceFileData(sourceFileName);
155                                        sourceFileDatas.put(sourceFileName, sourceFileData);
156                                }
157                                sourceFileData.addClassData(classData);
158                        }
159                }
160                finally
161                {
162                        lock.unlock();
163                }
164                return sourceFileDatas.values();
165        }
166
167        public int hashCode()
168        {
169                return this.name.hashCode();
170        }
171
172}