I am using the String split method and I want to have the last element.
The size of the Array can change.
Example:
String one = "Düsseldorf - Zentrum - Günnewig Uebachs"
String two = "Düsseldorf - Madison"
I want to split the above Strings and get the last item:
lastone = one.split("-")[here the last item] // <- how?
lasttwo = two.split("-")[here the last item] // <- how?
I don't know the sizes of the arrays at runtime :(
You could use lastIndexOf() method on String
String last = string.substring(string.lastIndexOf('-') + 1);
Save the array in a local variable and use the array's length field to find its length. Subtract one to account for it being 0-based:
String[] bits = one.split("-");
String lastOne = bits[bits.length-1];
Caveat emptor: if the original string is composed of only the separator, for example "-" or "---", bits.length will be 0 and this will throw an ArrayIndexOutOfBoundsException. Example: https://onlinegdb.com/r1M-TJkZ8
You can use the StringUtils class in Apache Commons:
StringUtils.substringAfterLast(one, "-");
using a simple, yet generic, helper method like this:
public static <T> T last(T[] array) {
return array[array.length - 1];
}
you can rewrite:
lastone = one.split("-")[..];
as:
lastone = last(one.split("-"));
String str = "www.anywebsite.com/folder/subfolder/directory";
int index = str.lastIndexOf('/');
String lastString = str.substring(index +1);
Now lastString has the value "directory"
Gathered all possible ways together!!
By using lastIndexOf() & substring() methods of Java.lang.String
// int firstIndex = str.indexOf( separator );
int lastIndexOf = str.lastIndexOf( separator );
String begningPortion = str.substring( 0, lastIndexOf );
String endPortion = str.substring( lastIndexOf + 1 );
System.out.println("First Portion : " + begningPortion );
System.out.println("Last Portion : " + endPortion );
split()Java SE 1.4. Splits the provided text into an array.
String[] split = str.split( Pattern.quote( separator ) );
String lastOne = split[split.length-1];
System.out.println("Split Array : "+ lastOne);
How to split String before first comma?
Java 8 sequential ordered stream from an array.
String firstItem = Stream.of( split )
.reduce( (first,last) -> first ).get();
String lastItem = Stream.of( split )
.reduce( (first,last) -> last ).get();
System.out.println("First Item : "+ firstItem);
System.out.println("Last Item : "+ lastItem);
Apache Commons Langjar « org.apache.commons.lang3.StringUtils
String afterLast = StringUtils.substringAfterLast(str, separator);
System.out.println("StringUtils AfterLast : "+ afterLast);
String beforeLast = StringUtils.substringBeforeLast(str, separator);
System.out.println("StringUtils BeforeLast : "+ beforeLast);
String open = "[", close = "]";
String[] groups = StringUtils.substringsBetween("Yash[777]Sam[7]", open, close);
System.out.println("String that is nested in between two Strings "+ groups[0]);
Guava: Google Core Libraries for Java. « com.google.common.base.Splitter
Splitter splitter = Splitter.on( separator ).trimResults();
Iterable<String> iterable = splitter.split( str );
String first_Iterable = Iterables.getFirst(iterable, "");
String last_Iterable = Iterables.getLast( iterable );
System.out.println(" Guava FirstElement : "+ first_Iterable);
System.out.println(" Guava LastElement : "+ last_Iterable);
Scripting for the Java Platform « Run Javascript on the JVM with Rhino/Nashorn
Rhino « Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically embedded into Java applications to provide scripting to end users. It is embedded in J2SE 6 as the default Java scripting engine.
Nashorn is a JavaScript engine developed in the Java programming language by Oracle. It is based on the Da Vinci Machine and has been released with Java 8.
Java Scripting Programmer's Guide
public class SplitOperations {
public static void main(String[] args) {
String str = "my.file.png.jpeg", separator = ".";
javascript_Split(str, separator);
}
public static void javascript_Split( String str, String separator ) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// Script Variables « expose java objects as variable to script.
engine.put("strJS", str);
// JavaScript code from file
File file = new File("E:/StringSplit.js");
// expose File object as variable to script
engine.put("file", file);
try {
engine.eval("print('Script Variables « expose java objects as variable to script.', strJS)");
// javax.script.Invocable is an optional interface.
Invocable inv = (Invocable) engine;
// JavaScript code in a String
String functions = "function functionName( functionParam ) { print('Hello, ' + functionParam); }";
engine.eval(functions);
// invoke the global function named "functionName"
inv.invokeFunction("functionName", "function Param value!!" );
// evaluate a script string. The script accesses "file" variable and calls method on it
engine.eval("print(file.getAbsolutePath())");
// evaluate JavaScript code from given file - specified by first argument
engine.eval( new java.io.FileReader( file ) );
String[] typedArray = (String[]) inv.invokeFunction("splitasJavaArray", str );
System.out.println("File : Function returns an array : "+ typedArray[1] );
ScriptObjectMirror scriptObject = (ScriptObjectMirror) inv.invokeFunction("splitasJavaScriptArray", str, separator );
System.out.println("File : Function return script obj : "+ convert( scriptObject ) );
Object eval = engine.eval("(function() {return ['a', 'b'];})()");
Object result = convert(eval);
System.out.println("Result: {}"+ result);
// JavaScript code in a String. This code defines a script object 'obj' with one method called 'hello'.
String objectFunction = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
engine.eval(objectFunction);
// get script object on which we want to call the method
Object object = engine.get("obj");
inv.invokeMethod(object, "hello", "Yash !!" );
Object fileObjectFunction = engine.get("objfile");
inv.invokeMethod(fileObjectFunction, "hello", "Yashwanth !!" );
} catch (ScriptException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static Object convert(final Object obj) {
System.out.println("\tJAVASCRIPT OBJECT: {}"+ obj.getClass());
if (obj instanceof Bindings) {
try {
final Class<?> cls = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror");
System.out.println("\tNashorn detected");
if (cls.isAssignableFrom(obj.getClass())) {
final Method isArray = cls.getMethod("isArray");
final Object result = isArray.invoke(obj);
if (result != null && result.equals(true)) {
final Method values = cls.getMethod("values");
final Object vals = values.invoke(obj);
System.err.println( vals );
if (vals instanceof Collection<?>) {
final Collection<?> coll = (Collection<?>) vals;
Object[] array = coll.toArray(new Object[0]);
return array;
}
}
}
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
}
}
if (obj instanceof List<?>) {
final List<?> list = (List<?>) obj;
Object[] array = list.toArray(new Object[0]);
return array;
}
return obj;
}
}
JavaScript file « StringSplit.js
// var str = 'angular.1.5.6.js', separator = ".";
function splitasJavaArray( str ) {
var result = str.replace(/\.([^.]+)$/, ':$1').split(':');
print('Regex Split : ', result);
var JavaArray = Java.to(result, "java.lang.String[]");
return JavaArray;
// return result;
}
function splitasJavaScriptArray( str, separator) {
var arr = str.split( separator ); // Split the string using dot as separator
var lastVal = arr.pop(); // remove from the end
var firstVal = arr.shift(); // remove from the front
var middleVal = arr.join( separator ); // Re-join the remaining substrings
var mainArr = new Array();
mainArr.push( firstVal ); // add to the end
mainArr.push( middleVal );
mainArr.push( lastVal );
return mainArr;
}
var objfile = new Object();
objfile.hello = function(name) { print('File : Hello, ' + name); }
JavaScript Array constructor or array literal.
With Guava:
final Splitter splitter = Splitter.on("-").trimResults();
assertEquals("Günnewig Uebachs", Iterables.getLast(splitter.split(one)));
assertEquals("Madison", Iterables.getLast(splitter.split(two)));
Splitter, Iterables
Since he was asking to do it all in the same line using split so i suggest this:
lastone = one.split("-")[(one.split("-")).length -1]
I always avoid defining new variables as far as I can, and I find it a very good practice
You mean you don't know the sizes of the arrays at compile-time? At run-time they could be found by the value of lastone.length and lastwo.length .
Also you can use java.util.ArrayDeque
String last = new ArrayDeque<>(Arrays.asList("1-2".split("-"))).getLast();
In java 8
String lastItem = Stream.of(str.split("-")).reduce((first,last)->last).get();
I guess you want to do this in i line. It is possible (a bit of juggling though =^)
new StringBuilder(new StringBuilder("Düsseldorf - Zentrum - Günnewig Uebachs").reverse().toString().split(" - ")[0]).reverse()
tadaa, one line -> the result you want (if you split on " - " (space minus space) instead of only "-" (minus) you will loose the annoying space before the partition too =^) so "Günnewig Uebachs" instead of " Günnewig Uebachs" (with a space as first character)
Nice extra -> no need for extra JAR files in the lib folder so you can keep your application light weight.
Related
I am a computer science university student working on my first 'big' project outside of class. I'm attempting to read through large text files (2,000 - 3,000 lines of text), line by line with buffered reader. When a keyword from a list of enums is located, I want it to send the current line from buffered reader to its appropriate method to be handled appropriatley.
I have a solution, but I have a feeling in my gut that there is a much better way to handle this situation. Any suggestions or feedback would be greatly appreciated.
Current Solution
I am looping through the the list of enums, then checking if the current enum's toString return is in the current line from buffered reader using the String.contains method.
If the enum is located, the enum is used in a switch statement for the appropriate method call. (I have 13 total cases just wanted to keep the code sample short).
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile.getAbsoluteFile()))){
while ((currentLine = reader.readLine()) != null) {
for (GameFileKeys gameKey : GameFileKeys.values()) {
if (currentLine.contains(gameKey.toString())) {
switch (gameKey) {
case SEAT -> seatAndPlayerAssignment(currentTableArr, currentLine);
case ANTE -> playerJoinLate(currentLine);
}
}
}
}
}
Previous Solution
Originally, I had a nasty list of if statements checking if the current line contained one of the keywords and then handled it appropriatley. Clearly that is far from optimal, but my gut tells me that my current solution is also less than optimal.
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile.getAbsoluteFile()))){
while ((currentLine = reader.readLine()) != null) {
if(currentLine.contains(GameFileKey.SEAT){
seatAndPlayerAssignment(currentTableArr, currentLine);
}
else if(currentLine.contains(GameFileKey.ANTE){
playerJoinLate(currentLine);
}
}
}
Enum Class
In case you need this, or have any general feedback for how I'm implementing my enums.
public enum GameFileKeys {
ANTE("posts ante"),
SEAT("Seat ");
private final String gameKey;
GameFileKeys(String str) {
this.gameKey = str;
}
#Override
public String toString() {
return gameKey;
}
}
I cannot improve over the core of your code: the looping on values() of the enum, performing a String#contains for each enum object’s string, and using a switch. I can make a few minor suggestions.
I suggest you not override the toString method on your enum. The Object#toString method is generally best used only for debugging and logging, not logic or presentation.
Your string passed to constructor of the enum is likely similar to the idea of a display name commonly seen in such enums. The formal enum name (all caps) is used internally within Java, while the display name is used for display to the user or exchanged with external systems. See the Month and DayOfWeek enums as examples offering a getDisplayName method.
Also, an enum should be named in the singular. This avoids confusion with any collections of the enum’s objects.
By the way, looks like you have a stray SPACE in your second enum's argument.
At first I thought it would help to have a list of all the display names, and a map of display name to enum object. However, in the end neither is needed for your purpose. I kept those as they might prove interesting.
public enum GameFileKey
{
ANTE( "posts ante" ),
SEAT( "Seat" );
private String displayName = null;
private static final List < String > allDisplayNames = Arrays.stream( GameFileKey.values() ).map( GameFileKey :: getDisplayName ).toList();
private static final Map < String, GameFileKey > mapOfDisplayNameToGameFileKey = Arrays.stream( GameFileKey.values() ).collect( Collectors.toUnmodifiableMap( GameFileKey :: getDisplayName , Function.identity() ) );
GameFileKey ( String str ) { this.displayName = str; }
public String getDisplayName ( ) { return this.displayName; }
public static GameFileKey forDisplayName ( final String displayName )
{
return
Objects.requireNonNull(
GameFileKey.mapOfDisplayNameToGameFileKey.get( displayName ) ,
"None of the " + GameFileKey.class.getCanonicalName() + " enum objects has a display name of: " + displayName + ". Message # 4dcefee2-4aa2-48cf-bf66-9a4bde02ac37." );
}
public static List < String > allDisplayNames ( ) { return GameFileKey.allDisplayNames; }
}
You can use a stream of the lines of your file being processed. Just FYI, not necessarily better than your code.
public class Demo
{
public static void main ( String[] args )
{
Demo app = new Demo();
app.demo();
}
private void demo ( )
{
try
{
Path path = Demo.getFilePathToRead();
Stream < String > lines = Files.lines( path );
lines.forEach(
line -> {
for ( GameFileKey gameKey : GameFileKey.values() )
{
if ( line.contains( gameKey.getDisplayName() ) )
{
switch ( gameKey )
{
case SEAT -> this.seatAndPlayerAssignment( line );
case ANTE -> this.playerJoinLate( line );
}
}
}
}
);
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
private void playerJoinLate ( String line )
{
System.out.println( "line = " + line );
}
private void seatAndPlayerAssignment ( String line )
{
System.out.println( "line = " + line );
}
public static Path getFilePathToRead ( ) throws IOException
{
Path tempFile = Files.createTempFile( "bogus" , ".txt" );
Files.write( tempFile , "apple\nSeat\norange\nposts ante\n".getBytes() );
return tempFile;
}
}
When run:
line = Seat
line = posts ante
I'm currently executing a rather complicated data pre-processing operation, this is:
cat large_file.txt \ | ./reverb -q | cut --fields=16,17,18 | awk -F\\t -vq="'" 'function quote(token) { gsub(q, "\\"q, token); return q token q } { print quote($2) "(" quote($3) ", " quote($1) ")." }' >> output.txt
As you can see, this is rather convoluted, first cat, then to that ./reverb, then to cut, and finally to awk.
Next I want to pass the output to a java program, i.e.:
public static void main(String[] args) throws IOException
{
Ontology ontology = new Ontology();
BufferedReader br = new BufferedReader(new FileReader("/home/matthias/Workbench/SUTD/2_January/Prolog/horn_data_test.pl"));
Pattern p = Pattern.compile("'(.*?)'\\('(.*?)','(.*?)'\\)\\.");
String line;
while ((line = br.readLine()) != null)
{
Matcher m = p.matcher(line);
if( m.matches() )
{
String verb = m.group(1);
String object = m.group(2);
String subject = m.group(3);
ontology.addSentence( new Sentence( verb, object, subject ) );
}
}
for( String joint: ontology.getJoints() )
{
for( Integer subind: ontology.getSubjectIndices( joint ) )
{
Sentence xaS = ontology.getSentence( subind );
for( Integer obind: ontology.getObjectIndices( joint ) )
{
Sentence yOb = ontology.getSentence( obind );
Sentence s = new Sentence( xaS.getVerb(),
xaS.getObject(),
yOb.getSubject() );
System.out.println( s );
}
}
}
}
What would be the best way to synthesize this process into one coherent operation? Ideally I'd like to just specify the input file and the output file and run it once. As it stands the entire process is quite discombobulated.
Maybe I can just put all these calls into a bash script? Is that feasible?
The input initially contains English language sentences, one per line, this is:
Oranges are delicious and contain vitamin c.
Brilliant scientists learned that we can prevent scurvy by imbibing vitamin c.
Colorless green ideas sleep furiously.
...
The pre-processing makes it look like this:
'contain'('vitamin c','oranges').
'prevent'('scurvy','vitamin c').
'sleep'('furiously','ideas').
...
The java program is for learning "rules" by inference, so if the processed data yields 'contain'('vitamin c','oranges'). & 'prevent'('scurvy','vitamin c'). then the java code will emit 'prevent'('scurvy','oranges').
I looked at the source code for reverb and I think it's very easy to adapt it to produce the output you want. If you look at the reverb class CommandLineReverb.java, it has the following two methods:
private void extractFromSentReader(ChunkedSentenceReader reader)
throws ExtractorException {
long start;
ChunkedSentenceIterator sentenceIt = reader.iterator();
while (sentenceIt.hasNext()) {
// get the next chunked sentence
ChunkedSentence sent = sentenceIt.next();
chunkTime += sentenceIt.getLastComputeTime();
numSents++;
// make the extractions
start = System.nanoTime();
Iterable<ChunkedBinaryExtraction> extractions = extractor
.extract(sent);
extractTime += System.nanoTime() - start;
for (ChunkedBinaryExtraction extr : extractions) {
numExtrs++;
// run the confidence function
start = System.nanoTime();
double conf = getConf(extr);
confTime += System.nanoTime() - start;
NormalizedBinaryExtraction extrNorm = normalizer
.normalize(extr);
printExtr(extrNorm, conf);
}
if (numSents % messageEvery == 0)
summary();
}
}
private void printExtr(NormalizedBinaryExtraction extr, double conf) {
String arg1 = extr.getArgument1().toString();
String rel = extr.getRelation().toString();
String arg2 = extr.getArgument2().toString();
ChunkedSentence sent = extr.getSentence();
String toks = sent.getTokensAsString();
String pos = sent.getPosTagsAsString();
String chunks = sent.getChunkTagsAsString();
String arg1Norm = extr.getArgument1Norm().toString();
String relNorm = extr.getRelationNorm().toString();
String arg2Norm = extr.getArgument2Norm().toString();
Range arg1Range = extr.getArgument1().getRange();
Range relRange = extr.getRelation().getRange();
Range arg2Range = extr.getArgument2().getRange();
String a1s = String.valueOf(arg1Range.getStart());
String a1e = String.valueOf(arg1Range.getEnd());
String rs = String.valueOf(relRange.getStart());
String re = String.valueOf(relRange.getEnd());
String a2s = String.valueOf(arg2Range.getStart());
String a2e = String.valueOf(arg2Range.getEnd());
String row = Joiner.on("\t").join(
new String[] { currentFile, String.valueOf(numSents), arg1,
rel, arg2, a1s, a1e, rs, re, a2s, a2e,
String.valueOf(conf), toks, pos, chunks, arg1Norm,
relNorm, arg2Norm });
System.out.println(row);
}
The first method is called per sentence and does the extraction. Then it calls the second method to print the tab separated values to the output stream. I guess all you have to do is implement your own version of the second method 'printExtr()'.
Suppose csv file contains
1,112,,ASIF
Following code eliminates the null value in between two consecutive commas.
Code provided is more than it is required
String p1=null, p2=null;
while ((lineData = Buffreadr.readLine()) != null)
{
row = new Vector(); int i=0;
StringTokenizer st = new StringTokenizer(lineData, ",");
while(st.hasMoreTokens())
{
row.addElement(st.nextElement());
if (row.get(i).toString().startsWith("\"")==true)
{
while(row.get(i).toString().endsWith("\"")==false)
{
p1= row.get(i).toString();
p2= st.nextElement().toString();
row.set(i,p1+", "+p2);
}
String CellValue= row.get(i).toString();
CellValue= CellValue.substring(1, CellValue.length() - 1);
row.set(i,CellValue);
//System.out.println(" Final Cell Value : "+row.get(i).toString());
}
eror=row.get(i).toString();
try
{
eror=eror.replace('\'',' ');
eror=eror.replace('[' , ' ');
eror=eror.replace(']' , ' ');
//System.out.println("Error "+ eror);
row.remove(i);
row.insertElementAt(eror, i);
}
catch (Exception e)
{
System.out.println("Error exception "+ eror);
}
//}
i++;
}
how to read two consecutive commas from .csv file format as unique value in java.
Here is an example of doing this by splitting to String array. Changed lines are marked as comments.
// Start of your code.
row = new Vector(); int i=0;
String[] st = lineData.split(","); // Changed
for (String s : st) { // Changed
row.addElement(s); // Changed
if (row.get(i).toString().startsWith("\"") == true) {
while (row.get(i).toString().endsWith("\"") == false) {
p1 = row.get(i).toString();
p2 = s.toString(); // Changed
row.set(i, p1 + ", " + p2);
}
...// Rest of Code here
}
The StringTokenizer skpis empty tokens. This is their behavious. From the JLS
StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
Just use String.split(",") and you are done.
Just read the whole line into a string then do string.split(",").
The resulting array should have exactly what you are looking for...
If you need to check for "escaped" commas then you will need some regex for the query instead of a simple ",".
while ((lineData = Buffreadr.readLine()) != null) {
String[] row = line.split(",");
// Now process the array however you like, each cell in the csv is one entry in the array
Suppose I have a simple program which takes argument input in one of the following forms
do1 inputLocation outputLocation
do2 inputLocation outputLocation
do3 [30 or 60 or 90] inputLocation outputLocation
do4 [P D or C] inputLocation outputLocation
do5 [G H I] inputLocation outputLocation
I also have 5 functions with the same names in the program that I need to call. So far I thought of doing it this way (In 'semi pseudocode')
static void main(String[] args)
{
if (args.length == 3)
processTriple(args);
if (args.length == 4)
processQuadruple(args);
throw new UnsupportedOperationException("dasdhklasdha");
}
where the process functions look like this
processDouble(String args[])
{
String operation = "args[0]";
Location input = getInput(args[1]);
Location output = getInput(args[2]);
if (operation.equals("do1"))
do1(input,output);
if (operation.equals("do2"))
do2(input,output);
... etc
}
The way I'm doing it doesn't seem very extensible. If a function's arguments change, or new functions are added it seems like this would be a pain to maintain.
What's the "best" way of going about something like this
at this point I would use commons-cli or jargs. Unless you are trying to do something really special with arguments I would say focus in the real business of your app and don't deal with the mess of the application arguments
Use a command line parsing library.
Ive used JOpt Simple in the past with great results. It lets you abstract away the command line arg mess, and keep a really clean update-able list of arguments. An added benefit is it will generate the help output that standard command line utilities have.
Heres a quick example:
private void runWithArgs (String[] args) {
OptionParser parser = getOptionParser ();
OptionSet options = null;
try {
options = parser.parse (args);
}
catch (OptionException e) {
log.error ("Sorry the command line option(s): " + e.options () +
" is/are not recognized. -h for help.");
return;
}
if (options.has ("h")) {
try {
log.info ("Help: ");
parser.printHelpOn (System.out);
}
catch (IOException e) {
log.error ("Trying to print the help screen." + e.toString ());
}
return;
}
if (options.has ("i")) {
defaultHost = (String) options.valueOf ("i");
}
if (options.has ("p")) {
defaultPort = (Integer) options.valueOf ("p");
}
if (options.has ("q")) {
String queryString = (String) options.valueOf ("q");
log.info ("Performing Query: " + queryString);
performQuery (queryString, defaultHost, defaultPort);
return;
}
}
You can use Cédric Beust's JCommander library
Because life is too short to parse command line parameters
I even creatively violate the original intent of the library to parse NMEA 0183 sentences like $GPRTE as follows:
import java.util.List;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.internal.Lists;
public class GPRTE {
#Parameter
public List<String> parameters = Lists.newArrayList();
#Parameter(names = "-GPRTE", arity = 4, description = "GPRTE")
public List<String> gprte;
}
Code snippet that processes NMEA 0183 sentence $GPRTE from $GPRTE,1,1,c,*37 into -GPRTE 1 1 c *37 to comply with JCommander parsing syntax:
/**
* <b>RTE</b> - route message<p>
* Processes each <b>RTE</b> message received from the serial port in following format:<p>$GPRTE,d1,d2,d3,d4<p>Example: $GPRTE,1,1,c,*37
* #param sequences result of {#link #Utils.process(String)} method
* #see <a href="http://www.gpsinformation.org/dale/nmea.htm#RTE">http://www.gpsinformation.org/dale/nmea.htm#RTE<a><p>*/
public static void processGPRTE(final String command){
final String NMEA_SENTENCE = "GPRTE";
final String PARAM = "\u0001";
final String DOLLAR = "\u0004";
final String COMMA = "\u0005";
String parsedString = command;
if (parsedString.contains("$"+NMEA_SENTENCE)){
parsedString = parsedString.replaceAll("\\$", DOLLAR+PARAM);
parsedString = parsedString.replaceAll(",", COMMA);
System.out.println("GPRTE: " + parsedString);
String[] splits = parsedString.split(DOLLAR);
for(String info: splits){
if (info.contains(PARAM+NMEA_SENTENCE)) {
info = info.replaceFirst(PARAM, "-");
System.out.println("GPRTE info: " + info);
String[] args = info.split(COMMA);
GPRTE cmd = new GPRTE();
new JCommander(cmd, processEmptyString(args));
List<String> message = cmd.gprte;
String data1 = SerialOutils.unescape(message.get(0));
System.out.println("GPRTE: data1 = " + data1);
String data2 = SerialOutils.unescape(message.get(1));
System.out.println("GPRTE: data2 = " + data2);
String data3 = SerialOutils.unescape(message.get(2));
System.out.println("GPRTE: data3 = " + data3);
String data4 = SerialOutils.unescape(message.get(3));
System.out.println("GPRTE: data4 = " + data4);
System.out.println("");
}
}
}
}
I've used args4j with successful results before as well.
Just another option.
I am new to eclipse plugin development and I am trying to convert a IMethod to a string representation of the full method name. I.E.
my.full.package.ClassName.methodName(int param, String string)
so far I have had to hand roll my own solution. Is there a better way?
private static String getMethodFullName(IMethod iMethod)
{
String packageString = "[Default Package]";
try {
IPackageDeclaration[] declarations = iMethod.getCompilationUnit().getPackageDeclarations();
if(declarations.length > 0)
{
packageString = declarations[0].getElementName();
}
} catch (JavaModelException e) {
}
String classString = iMethod.getCompilationUnit().getElementName();
classString = classString.replaceAll(".java", "");
String methodString = iMethod.getElementName() + "(";
for (String type : iMethod.getParameterTypes()) {
methodString += type + ",";
}
methodString += ")";
return packageString + "." + classString + "." + methodString;
}
You can get the Fully qualified name for the type using
method.getDeclaringType().getFullyQualifiedName();
This is probably easier than accessing the package from the compilation unit. The rest of you function looks correct.
One small point: you should use StringBuilder to build up the string instead of adding to a standard String. Strings are immutable so addition creates loads of unrecesary temparary objects.
private static String getMethodFullName(IMethod iMethod)
{
StringBuilder name = new StringBuilder();
name.append(iMethod.getDeclaringType().getFullyQualifiedName());
name.append(".");
name.append(iMethod.getElementName());
name.append("(");
String comma = "";
for (String type : iMethod.getParameterTypes()) {
name.append(comma);
comma = ", ";
name.append(type);
}
name.append(")");
return name.toString();
}
Thanks to iain and some more research I have come up with this solution. It seems like something like this should be built into the JDT....
import org.eclipse.jdt.core.Signature;
private static String getMethodFullName(IMethod iMethod)
{
StringBuilder name = new StringBuilder();
name.append(iMethod.getDeclaringType().getFullyQualifiedName());
name.append(".");
name.append(iMethod.getElementName());
name.append("(");
String comma = "";
String[] parameterTypes = iMethod.getParameterTypes();
try {
String[] parameterNames = iMethod.getParameterNames();
for (int i=0; i<iMethod.getParameterTypes().length; ++i) {
name.append(comma);
name.append(Signature.toString(parameterTypes[i]));
name.append(" ");
name.append(parameterNames[i]);
comma = ", ";
}
} catch (JavaModelException e) {
}
name.append(")");
return name.toString();
}
I am not sure it would take into account all cases (method within an internal class, an anonymous class, with generic parameters...)
When it comes to methods signatures, the classes to look into are:
org.eclipse.jdt.internal.corext.codemanipulation.AddUnimplementedMethodsOperation
org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2
You need to get the jdt.core.dom.IMethodBinding, from which you can extract all what you need.
If you have a MethodInvocation, you can:
//MethodInvocation node
ITypeBinding type = node.getExpression().resolveTypeBinding();
IMethodBinding method=node.resolveMethodBinding();