Question

Hi I have a problem that I can't solve. A have exported pacakges from the jar manifest in form of String and I want to put it in Map where key is the name of the package and the rest information in value. You will say that is peace of cake but lets show you what exactly I want to do. I have a String, I little piece from it

 aQute.bnd.annotation;version="1.43.1",aQute.bnd.annotati
 on.component;version="1.43.1",aQute.bnd.annotation.metatype;version="1.
 43.1",aQute.bnd.ant;uses:="aQute.service.reporter,org.apache.tools.ant,
 org.apache.tools.ant.taskdefs,org.apache.tools.ant.types";version="0.0.
 0",aQute.bnd.build;version="2.1.0";uses:="aQute.bnd.maven.support,aQute
 .bnd.osgi,aQute.bnd.service,aQute.bnd.service.action,aQute.bnd.version,
 aQute.service.reporter",aQute.bnd.build.model;version="2.3";uses:="aQut
 e.bnd.build.model.clauses,aQute.bnd.properties,aQute.bnd.version,org.os
 gi.resource",aQute.bnd.build.model.clauses;version=2;uses:="aQute.bnd.h
 eader",aQute.bnd.build.model.conversions;uses:="aQute.bnd.build.model,a
 Qute.bnd.build.model.clauses,aQute.bnd.header,aQute.libg.tuple,org.osgi
 .resource";version="0.0.0"

If I split it on comma(,) in the keys there will be wrong peaces because we have

aQute.bnd.ant;uses:="aQute.service.reporter,org.apache.tools.ant,
 org.apache.tools.ant.taskdefs,org.apache.tools.ant.types";version="0.0.
 0"

where in uses clause we separate the name of the dependent packs with comma too. So the line above have to be in my output map as:

Key: aQute.bnd.ant
Value: uses:="aQute.service.reporter,org.apache.tools.ant,
 org.apache.tools.ant.taskdefs,org.apache.tools.ant.types";version="0.0.
 0"

So which String methods or regex to use to do my work?

Était-ce utile?

La solution

//split at , only if it's not within ""
String[] packages=input.split(",(?=([^\"]*\"[^\"]*\")+[^\"]*$)");
for(String pack:packages)
{
    String[] output=pack.split("(?=uses:=)");
    output[0];//key
    if(output.length==2)//incase if there's no value
    output[1];//value
}

Edit

(?=uses:=) is a lookahead which would match at the position which is followed by uses:=..Now we could have used uses:= as regex but that would eat uses:=...To avoid it we use zero width lookahead

Autres conseils

Sometimes the long way is the easiest way:

public static Map<String, String> parse(String s) {
    Map<String, String> allPackageInfo = new HashMap<>();

    CharacterIterator i = new StringCharacterIterator(s);
    char c = i.first();
    while (c != CharacterIterator.DONE) {
        StringBuilder packageName = new StringBuilder();
        while (c != ';' && c != CharacterIterator.DONE) {
            packageName.append(c);
            c = i.next();
        }

        if (c == ';') {
            c = i.next();
        }

        StringBuilder packageInfo = new StringBuilder();
        while (c != ',' && c != CharacterIterator.DONE) {
            if (c == '"') {
                do {
                    packageInfo.append(c);
                    c = i.next();
                } while (c != '"');
            }
            packageInfo.append(c);
            c = i.next();
        }

        if (c == ',') {
            c = i.next();
        }

        allPackageInfo.put(packageName.toString(), packageInfo.toString());
    }

    return allPackageInfo;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top