/*
 * fb-contrib - Auxiliary detectors for Java programs
 * Copyright (C) 2005-2015 Dave Brosius
 * 
 * This library 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 library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package com.mebigfatguy.fbcontrib.detect;

import java.util.HashSet;
import java.util.Set;

import com.mebigfatguy.fbcontrib.utils.BugType;
import com.mebigfatguy.fbcontrib.utils.FQMethod;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;

/**
 * looks for method calls to collection classes where the method is not defined
 * by the Collections interface, and an equivalent method exists in the
 * interface.
 */
public class NonCollectionMethodUse extends BytecodeScanningDetector {
    private static Set<FQMethod> oldMethods = new HashSet<FQMethod>();

    static {
        oldMethods.add(new FQMethod("java/util/Hashtable", "contains", "(java/lang/Object)Z"));
        oldMethods.add(new FQMethod("java/util/Hashtable", "elements", "()Ljava/util/Enumeration;"));
        oldMethods.add(new FQMethod("java/util/Hashtable", "keys", "()Ljava/util/Enumeration;"));
        oldMethods.add(new FQMethod("java/util/Vector", "addElement", "(Ljava/lang/Object;)V"));
        oldMethods.add(new FQMethod("java/util/Vector", "elementAt", "(I)Ljava/lang/Object;"));
        oldMethods.add(new FQMethod("java/util/Vector", "insertElementAt", "(Ljava/lang/Object;I)V"));
        oldMethods.add(new FQMethod("java/util/Vector", "removeAllElements", "()V"));
        oldMethods.add(new FQMethod("java/util/Vector", "removeElement", "(Ljava/lang/Object;)Z"));
        oldMethods.add(new FQMethod("java/util/Vector", "removeElementAt", "(I)V"));
        oldMethods.add(new FQMethod("java/util/Vector", "setElementAt", "(Ljava/lang/Object;I)V"));
    }

    private BugReporter bugReporter;

    /**
     * constructs a NCMU detector given the reporter to report bugs on
     * 
     * @param bugReporter
     *            the sync of bug reports
     */
    public NonCollectionMethodUse(BugReporter bugReporter) {
        this.bugReporter = bugReporter;
    }

    @Override
    public void sawOpcode(int seen) {
        if (seen == INVOKEVIRTUAL) {
            String className = getClassConstantOperand();
            String methodName = getNameConstantOperand();
            String methodSig = getSigConstantOperand();

            FQMethod methodInfo = new FQMethod(className, methodName, methodSig);
            if (oldMethods.contains(methodInfo)) {
                bugReporter.reportBug(new BugInstance(this, BugType.NCMU_NON_COLLECTION_METHOD_USE.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                        .addSourceLine(this));
            }
        }
    }
}

@@ -883,34 +883,8 @@
 t;%0A%0A
-import java.util.HashSet;%0A
 impo
@@ -901,16 +901,16 @@
 il.Set;%0A
+
 %0Aimport 
@@ -998,16 +998,72 @@
 QMethod;
+%0Aimport com.mebigfatguy.fbcontrib.utils.UnmodifiableSet;
 %0A%0Aimport
@@ -1454,16 +1454,22 @@
  static 
+final 
 Set%3CFQMe
@@ -1491,70 +1491,40 @@
 s = 
-new HashSet%3CFQMethod%3E();%0A%0A    static %7B%0A        oldMethods.add(
+UnmodifiableSet.create(%0A        
 new 
@@ -1585,26 +1585,25 @@
 g/Object)Z%22)
-);
+,
 %0A        old
@@ -1595,39 +1595,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -1667,34 +1667,33 @@
 l/Enumeration;%22)
-);
+,
 %0A        oldMeth
@@ -1681,39 +1681,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -1757,18 +1757,17 @@
 ation;%22)
-);
+,
 %0A       
@@ -1763,39 +1763,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -1834,26 +1834,25 @@
 /Object;)V%22)
-);
+,
 %0A        old
@@ -1844,39 +1844,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -1918,18 +1918,17 @@
 bject;%22)
-);
+,
 %0A       
@@ -1924,39 +1924,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -2001,26 +2001,25 @@
 Object;I)V%22)
-);
+,
 %0A        old
@@ -2011,39 +2011,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -2071,26 +2071,25 @@
 nts%22, %22()V%22)
-);
+,
 %0A        old
@@ -2081,39 +2081,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -2159,18 +2159,17 @@
 ect;)Z%22)
-);
+,
 %0A       
@@ -2165,39 +2165,24 @@
 %22),%0A        
-oldMethods.add(
 new FQMethod
@@ -2224,26 +2224,25 @@
 At%22, %22(I)V%22)
-);
+,
 %0A        old
@@ -2242,23 +2242,8 @@
     
-oldMethods.add(
 new 
@@ -2316,16 +2316,15 @@
 )V%22)
-);
 %0A    
-%7D
+);
 %0A%0A  

simplify with UnmodifiableSet.create