# regualar expression für Konstruktoren



## Isaac (22. Jul 2004)

Allgemein kann man über einen Konstruktor sagen das er am Anfang erstmal einen Namen hat wie die Datei selbst. 
Zweitens hat er mindestens 0 oder maximal unendliche viele Parameter in der Ausprägung (Qualifier Name) und das ganze Komma separiert. Zwischen den Abschnitten könne belieg viele leer und carriage returns sein.


```
xxxx(
        yyy zzz,
        aaa bbb)
        throws iiii
    {
        super(zzz, bbb);
    }
```


Ich hab schon alles mir mögliche Versucht und nachgelesen aber ich bekomme dafür keine regex aufgestellt obwohl es eigentlich machbar sein sollte. Sind alle Paramter auf einer Zeile ist es kein Problem. Dann kann man sagen

Freihand, nicht getestet
(?<=\w+\s{0, 100}\().*(?=\))

Im Klartext, wenn du etwas findest das so aussieht "xxx         (" dann nimm alle Zeichen die dahiner kommen bis zum ")" mit. Diesen String könnte man dann in einen Tokenizer stecken. Aber das ist nicht allgemein genug da .* am Zeilenende aufhört zu lesen. Wenn man das Pattern das compiliert wird auf DOTALL stellt, also über das Zeilenende hinaus kommt einem eine andere eigenschaft des * in die Quere, er ist gierig. Er liest alles bis zum letzen gefunden ) ein. Was dazu führt das man quasi die ganze Datei zurück bekommt. 

Mir fällt dafür keine Lösung ein die man allgemein abhandeln könnte. Hat sonst jemand eine Idee? Ich werds nun erstmal mit einem normalen Tokenizer versuchen der sich die Konstruktoren rauspult. Eine allgemeine Lösung wäre mir aber lieber.


----------



## bygones (22. Jul 2004)

Isaac hat gesagt.:
			
		

> einem eine andere eigenschaft des * in die Quere, er ist gierig


Dann verbiete ihm doch die Gier  :wink: 

```
(?<=\w+\s{0, 100}\().*?(?=\))
```
das *?* verhindert die Gier eines ausdrucks


----------



## Isaac (22. Jul 2004)

Wieder was gelernt, danke dir. Das wusste ich noch nicht und gefunden habe ich es auch nicht  :? 

Werd ich gleich mal ausprobieren.


----------



## Isaac (22. Jul 2004)

Wieder mal just für den Fall das jemand interesse hat.

Hier das organize imports das im moment aber nur alle imports ausgibt die man importieren muss (interne Klassen müssen noch abgezogen werden da die im moment mit ausgegeben werden). Ein weiteres Defizit ist, das Klassen die nur statische Sachen enthalten nicht erkannt werden. Also z.b. String s = StatischeKlasse.HALLO; 

Die "StatischeKlasse" wird nicht erkannt. 

Alle anderen werden aber, bei mir jedenfalls im Moment sauber erkannt.
In der Main Klasse sieht man ein "list.add("JDFAutotest.java");". Hier können beliebig viele Klassen zu der list hinzugefügt werden, auch mit kompletten Pfadnamen, aber nicht mit /. Ich arbeite mit line.seperator und / ist invalid auf windows systemen.

Das Programm arbeitet mit 3 Queues die parallel abgearbeitet werden wenn was im Queue ist.

Es wäre cool wenn ihr es mal testen könntet, vieleicht habe ich irgenwelche imports vergessen. Ich habs heute erstmal mit 40 Klassen getestet und bis auf die static Klassen war alles sauber.


EDIT: Dieses Programm schreibt noch nix raus. Es liest nur die Klasse ein und schreibt alle imports ohne Packageanweisung auf die Konsole. Es geht also beim Probieren nix kaputt.

Gruss, 
Isa


```
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * INFO: here are the regex definitions with are used to find 
 * the imports. These one are in one long regex inside the method. Thats 
 * why they are split apart here. Others are used also, these are not 
 * mentioned here.
 * 
 * regex to find declarations "\\w+(?=\\s+\\w+\\s*=)"
 * regex to find methods      "\\w+(?=\\s+\\w+\\s*\\(.*\\)\\s*\\{)"
 * regex to find new          "(?<=new\\s{1,100})\\w+";
 * regex to find throws       "(?<=throws\\s{1,100})\\w+"
 * regex to find catches      "(?<=catch\\s{0,100}\\(\\s{0,100})\\w+"
 * regex to find extends      "(?<=extends\\s{1,100})\\w+"
 * 
 * @author Mattern
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class OrganizeImports
{
    private static final ArrayList  knownTypes          = new ArrayList();
    
    private final   String          EMPTYSTRING         = "";
    private final   String          BLANK               = " ";
    private final   String          COMMA               = ",";
    private final   String          lineSep             = System.getProperty("line.separator");
    private final   String          fileSep             = System.getProperty("file.separator");
    private         String          strFileName         = EMPTYSTRING;
    
    private         boolean         bLoadFilesDone      = false;
    private         boolean         bfindImportsDone    = false;
    private         boolean         bWriteFilesDone     = false;
    
    private         ArrayList       loadQueue           = new ArrayList();
    private         ArrayList       findImportQueue     = new ArrayList();
    private         ArrayList       writeFiles          = new ArrayList();
    
    private         ArrayList       paths               = new ArrayList();
    
    /**
     * Organizes imports for most files with some limitations
     * 
     * @param strPath complete path "C:\test.java" for example
     * @return true if done
     */
    public void organizeImports(ArrayList strPaths)
    {
        paths.addAll(strPaths);
        loadFile();
        findImports();
        writeImports();
    }
   
    private ArrayList getFilePaths()
    {
        return paths; 
    }
    
    private void setFilePaths(ArrayList list)
    {
        paths = list;
    }
    
    private void loadFile()
    {
        new Thread()
        {
            public void run()
            {
                Iterator it = paths.iterator();
                while(it.hasNext())
                {
                    String strFilePath          = (String)it.next();
                    String strFileName          = strFilePath.substring(strFilePath.lastIndexOf(fileSep) + 1, strFilePath.length() - 5); 
                    StringBuffer buff           = new StringBuffer(1000);
                    String line                 = EMPTYSTRING;
                    
                    try
                    {
                        BufferedReader br = new BufferedReader(new FileReader(strFilePath));
                        
                        while((line = br.readLine()) != null)
                        {
                            buff.append(line);
                            buff.append(lineSep);
                        }
                        loadQueue.add(new String[] { buff.toString(), strFileName } );
                    }
                    catch(IOException ioe){ioe.printStackTrace();}
                }
                bLoadFilesDone = true;
            }
        }.start();
        
    }
    
    
    private void findImports()
    {
        new Thread()
        {
            public void run()
            {
                while(!loadQueue.isEmpty() || bLoadFilesDone == false)
                {
                    if(loadQueue.isEmpty())
                    {
                        try
                        {
                            sleep(100);
                        }
                        catch(InterruptedException e) {e.printStackTrace();}
                    }
                    else
                    {
                        String[] params = (String[])loadQueue.get(0);
                        
                        String strFileContent       = params[0];
                        String strFileName          = params[1];
                        String regex_constructor    = "(?<=" + strFileName + "\\s{0,100}\\().*?(?=\\))";
                        Pattern constructorPattern  = Pattern.compile(regex_constructor, Pattern.DOTALL);
                        Pattern importsToFind                = Pattern.compile("\\w+(?=\\s+\\w+\\s*=)|\\w+(?=\\s+\\w+\\s*\\(.*\\)\\s*\\{)|(?<=new\\s{1,100})\\w+|(?<=throws\\s{1,100})\\w+|(?<=catch\\s{0,100}\\(\\s{0,100})\\w+|(?<=extends\\s{1,100})\\w+");
                        Pattern[] patternSet        = new Pattern[] { importsToFind };
                        
                        TreeSet set = new TreeSet();
                        for (int i = 0; i < patternSet.length; i++)
                        {
                            Matcher findMatches = patternSet[i].matcher(strFileContent);
                            while (findMatches.find()) 
                            {
                                String s = findMatches.group(); 
                                set.add(s);
                            }
                        }
                        
                        //special regex for constructors
                        Matcher findMatches = constructorPattern.matcher(strFileContent);
                        while (findMatches.find()) 
                        {
                            String s = findMatches.group(); 
                            StringTokenizer st = new StringTokenizer(s, COMMA);
                            while(st.hasMoreTokens())
                            {
                                String token = st.nextToken();
                                token = token.trim();
                                int i = token.indexOf(BLANK);
                                if(i != -1)
                                {
                                    token = token.substring(0, i);
                                    set.add(token);
                                }
                            }
                        }
                        set.removeAll(knownTypes);
                        findImportQueue.add(set);
                        loadQueue.remove(0);
                    }
                }
                bfindImportsDone = true;
            }
        }.start();
        
    }

    private void writeImports()
    {
        new Thread()
        {
            public void run()
            {
                while(!findImportQueue.isEmpty() || bfindImportsDone == false)
                {
                    if(findImportQueue.isEmpty())
                    {
                        try
                        {
                            sleep(100);
                        }
                        catch(InterruptedException e) {e.printStackTrace();}
                    }
                    else
                    {
                        TreeSet set = (TreeSet)findImportQueue.get(0);
                        Iterator it = set.iterator();
                        while(it.hasNext())
                        {
                            System.out.println(it.next());
                        }
                        findImportQueue.remove(0);
                    }
                }
                bWriteFilesDone = true;
            }
        }.start();
    }
    
    static
    {
        knownTypes.add("String");
        knownTypes.add("int");
        knownTypes.add("double");
        knownTypes.add("long");
        knownTypes.add("float");
        knownTypes.add("byte");
        knownTypes.add("char");
        knownTypes.add("void");
        knownTypes.add("boolean");
        knownTypes.add("private");
        knownTypes.add("static");
        knownTypes.add("public");
        knownTypes.add("protected");
    }
    

    public static void main(String[] args) 
    {
        OrganizeImports orgImps = new OrganizeImports();
        ArrayList list = new ArrayList();
        list.add("JDFAutotest.java");
        orgImps.organizeImports(list);
    }
}
```


----------



## Tobias (23. Jul 2004)

Das geht doch auch einfacher (ohne zu wissen, was du eigentlich tun willst): Mit dem Reflection-API! Die kann dir alle verfügbaren Konstruktoren ausgeben...

mpG
Tobias

_Vergiss alles, was ich gesagt habe. Deine Aufgabenstellung läßt sich mit der Reflection-API nicht lösen. Dafür aber mit einer gescheiten IDE ._


----------

