I'm trying to determine if a list contains a object, if it does then run a method to clear the original list (in a singleton class), then repopulate the list minus the one I ran the condition over.
public void removeSelectedItem(Object obj){
SearchBuilder builder = SearchBuilder.getInstance();
try {
String methodName = labelToMethod.get(getTitle());
if( methodName == null ){
methodName = getTitle().replace(" ","");
}
Method m = builder.getClass().getMethod("get"+methodName);
Object r = m.invoke(builder);
if( r != null ){
if( r instanceof Integer ){
if( ((Integer) r).intValue() == ((Integer) obj).intValue() ) {
setSelectedItem(null);
}
} else if ( r instanceof String ){
if(r.equals(obj)) {
setSelectedItem(null);
}
} else if ( r instanceof ArrayList ){
Log.d("TEST",((ArrayList) r).size()+"");
if( ((ArrayList) r).contains(obj) ){
Log.d("TEST", "R CONTAINS OBJ");
Log.d("TEST", "BEFORE: " + ((ArrayList) r).size() + "");
clearSelectedItem();
Log.d("TEST","AFTER: " + ((ArrayList) r).size() + "");
for ( int i = 0; i < ((ArrayList) r).size(); i++ ){
Log.d("TEST","IN FOR LOOP" + i);
if( !((ArrayList) r).get(i).equals(obj) ){
Log.d("TEST", "SETTING VALUES");
setSelectedItem(((ArrayList) r).get(i));
}
}
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
The clearSelectedItem method is:
public void clearSelectedItem(){
SearchBuilder builder = SearchBuilder.getInstance();
try {
String methodName = labelToMethod.get(getTitle());
if( methodName == null ){
methodName = getTitle().replace(" ","");
}
Method m = builder.getClass().getMethod("clear"+methodName);
m.invoke(builder);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
The output I'm getting is:
D/TEST : 2
D/TEST : R CONTAINS OBJ
D/TEST : BEFORE: 2
D/TEST : AFTER: 0
So it's not entering the loop, as the ArrayList size has been reduced to 0. But what I don't understand is, why has the ArrayList been reduced? Surely the object has been set as part of the m.invoke call earlier in the removeSelectedItem method, and the clearSelectedItem doesn't touch this response?
I'm rather new to Java, so any insight would be great!
EDIT:
So I've managed to solve my problem, but would still really like some insight into what's going on...
I've solved it by cloning the ArrayList:
} else if ( r instanceof ArrayList ){
Object c = ((ArrayList) r).clone();
if( ((ArrayList) c).contains(obj) ){
clearSelectedItem();
for ( int i = 0; i < ((ArrayList) c).size(); i++ ){
if( !((ArrayList) c).get(i).equals(obj) ){
setSelectedItem(((ArrayList) c).get(i));
}
}
}
}
So I dont understand why you are repopulating the list itself,
would it be much cleaner or neat if you just use
if(list.contain(object))
{
list.remove(object);
}
or if you want to remove all of them just use
while(list.contain(object))
{
list.remove(object);
}
So after a little more research, Java is pass-by-value, which means that it passes the reference to the ArrayList, rather than create a new ArrayList with the same values. Amending Object r in any way affects the original ArrayList in SearchBuilder itself.
http://www.javaranch.com/campfire/StoryPassBy.jsp
Related
given a TestNG test within Selenium
public boolean TestTabTagLog( Matters m, String logfile) {
boolean passFail = false;
if( m == null) {
System.out.println("TestTagTabLog: m is null and should not be!");
} else {
System.out.println("TestTabTagLog: m.getPageName: " + m.getPageName());
/* m does get here and is populated , great*/
}
WebElement divTopTabs = m.getDriver().findElement(By.id("tab-topTabs"));
// --- this fails with an NoSuchElementException --- why? -- and more importantly, how to fix?
/* more logic goes here */
return passFail;
}
#Test()
public boolean runTest( Matters m, String testToRun) {
boolean passFail = false;
List<Boolean> results = new LinkedList<Boolean>();
Matters m = new Matters();
WebElement divTopTabs = m.getDriver().findElement(By.id("tab-topTabs"));
// m and divTopTabs exist and are populated
List<String> list_tabName = new LinkedList<String>();
list_tabName.add("TagLog");
for( String tabName : list_tabName) {
String functName = "TestTab" + tabName;
try {
Class c = Class.forName("foo.fighters.Test");
Object obj = c.newInstance();
Class[] params = new Class[2];
params[0] = Matters.class;
params[1] = String.class;
Method mth = c.getDeclaredMethod( functName, params);
mth.setAccessible(true);
Boolean result = (Boolean) mth.invoke( obj, m, "C:/User/Me/alogfile.txt");
results.add( result);
} catch ( ClassNotFoundException cnfe) {
System.out.println("cnfe:" + cnfe.getMessage());
} catch ( InstantiantionException | IllegalAccessException iae) {
System.out.println("iae:" + iae.getMessage());
} catch ( NoSuchMethodException | SecurityException nsme) {
System.out.println("nsme:" + nsme.getMessage());
} catch ( IllegalArgumentException | InvocationTargetException ite ) {
System.out.println("ite:" + ite.getMessage());
}
}
Boolean atLeastOneTestFailed = results.stream()filter(e -> e == false).findAny().isPresent();
if( !atLeastOneTestFailed) {
passFail = true;
}
return passFail;
}
I'm trying to dynamically call my functions by name - hoping to prevent coding a giant switch/case statement.
Within the top function runTest() I can find m and use m to find divTopTabs.
I can pass m to called function TestTabTagLog but within TestTabTagLog canNOT use m to find divTopTags. That's my problem.
I have tried passing in divTopTabs to TestTabTagLog as an argument but that doesn't work for some reason, maybe cuz it's a WebElement and that is a class inside openqa ie not a class I create within my project like Matters. But it that's true why can I pass in the String logfile ?
A little out of my depth here, could use some help/advice/constructive critism
TIA,
Still-learning Steve
I can't find a way to keep my program running after it catch and error.
For example, I have:
String[] num={"1","2","3","NotNumber","4","5"};
I want to convert all into Integer, so num[3] is invalid, but I want keep running to num[4] and num[5] after it catch the error.
How can I do so?
It would have helped if you had shown what you had tried so far, but the simplest solution is to wrap your int.parse() in a try/catch block and swallow the exception.
for(int i = 0; i < items.length; i++) {
try {
newItems[i] = Itemger.parseInt(items[i]);
catch(Exception ex) {
// do nothing
}
}
Put the try-catch block inside your iteration
JAVA 7
List<Integer> intList = new ArrayList<>();
for(String s : num) {
try {
Integer n = Integer.valueOf(s);
intList.add(n);
} catch (Exception ex) { continue; }
}
JAVA 8 Streams
List<Integer> intList = Arrays.asList(num)
.stream()
.map(s -> {
try {
return Integer.valueOf(s);
} catch(Exception ex) { return null;}
})
.filter(i -> i != null)
.collect(Collectors.toList());
today i've occured some strange error, but i'll give my best to explain it because i can't solve it!
First of all thats the method which makes problems, BUT only after loading an object via FileInputStream!
The error is that it returns false instead of returning true, even when the searched object is in the saved array
public boolean isCarOwned(String pName) { //find Car in Array with pName
for(int x = 0; x < carCount; x++) { // carCount = array length
if(carInv[x] != null) { //check if array is empty
if(carInv[x].getName() == pName) { //check if car in array has pName
return true;
}
}
}
return false;
}
When i'm loading an Object with the following method the upper method won't work : (i'm also saving this object with an similar way (write instead if load Object) )
ObjectInputStream invLoad;
try {
invLoad = new ObjectInputStream(new FileInputStream("save/inv_data.bin"));
Main.inv = (Inventory) invLoad.readObject();
invLoad.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
Thats the Object i'm saving and loading:
public Car(String pName, int pSpeed, int pSpace, int pPrice, String pCarIcon) {
name = pName;
speed = pSpeed;
space = pSpace;
price = pPrice;
carIcon = new ImageIcon(pCarIcon); }
And thats the "carInv" Array if this is important:
private Car carInv[] = new Car[10];
I apologize for this huge amount of code but i don't know where the error is, so i'm trying to give you all important information.
So thank you very much for reading all this, i hope you got an idea or solution for me.
public boolean isCarOwned(String pName) { //find Car in Array with pName
for(int x = 0; x < carCount; x++) { // carCount = array length
if(carInv[x] != null && carInv[x].equals(pName)) { // if x-th value is not null and is equal to pName
return true;
}
}
return false;
}
The issue was that you were not using the equals method for comparing String objects. Have a look at this post for further explanation
I am not able to update the value of a global variable in a function which is called continuously by a thread
The function code is:
public void readMessages()
{
if (srv.getServiceStatus() == Service.ServiceStatus.STARTED) {
try {
InboundMessage msg = null;
java.util.LinkedList<InboundMessage> list = new java.util.LinkedList<InboundMessage>();
srv.readMessages(list, InboundMessage.MessageClasses.UNREAD);
int checkArray = list.size();
for (int i = 0; i < list.size(); i++) {
msg = list.get(i);
System.out.println("New incoming message from: " + msg.getOriginator() +" : \t" + msg.getText() + "\n");
saveSMS(msg.getOriginator(),msg.getText());
if (checkArray == 0) {
messageArray = new String [4];
for (int j = 0 ; j<4 ; j++) {
messageArray[j] = "";
}
}
if (noOfSms < 4) {
messageArray[noOfSms] = msg.getText();
noOfSms = noOfSms + 1;
}
if (noOfSms == 3) {
Receiver r = new Receiver ();
r.Processing_ReceivedSMS(msg.getText(),msg,messageArray);
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
Here noOfSms is the global variable but its value does not change.
The function from which readMessage is called is this:
public void run(){
while (true){
readMessages();
try {
t.sleep(5000);
user_status=2;
} catch (InterruptedException e) {
System.out.println("Thread Pause Exception");
}
}
}
What's the reason behind it and what to do about it?
Since you invoke this method from thread/s there are two reasons why your variable does not get updated.
the code inside readMessages() might throw any Exception before your variable gets updated
there is a possibility that your variable never updates because it is located inside if blocks. Check the initial value of it so it can pass the if-condition
I am trying to do autocomplete when I type in characters in ice:selectInputText
Issue I am facing is when I type in characters it brings even names which is not matching with the characters I type.
See the below screen shot for reference.
Ideally autocomplete should display only the first row from the result, however it displays rows which are not matching my typed characters.
Only Abell Maryland 20606 should display.
This is the code which is using for the comparison, how can I modify this to suit to my requirement which is to display only those results which is matching to what I type.
public int compare(Object o1, Object o2) {
if (o1 instanceof SelectItem) {
s1 = ((SelectItem) o1).getLabel();
} else {
s1 = o1.toString();
}
if (o2 instanceof SelectItem) {
s2 = ((SelectItem) o2).getLabel();
} else {
s2 = o2.toString();
}
return s1.compareToIgnoreCase(s2);
}
};
I am following this tutorial from Icefaces
http://wiki.icefaces.org/display/ICE/Auto-Complete
Update
My code in autocomplete.jspx
<ice:selectInputText rows="10" width="300"
listVar="emp"
valueChangeListener="#{mybean.updateList}"
listValue="#{mybean.list}">
<f:facet name="selectInputText">
<ice:panelGrid columns="3" columnClasses="empNameCol">
<ice:outputText value="#{emp.empName}"/>
</ice:panelGrid>
method updateList
public void updateList(ValueChangeEvent event) {
setMatches(event);
if (event.getComponent() instanceof SelectInputText) {
SelectInputText autoComplete = (SelectInputText)event.getComponent();
if (autoComplete.getSelectedItem() != null) {
bean = (Bean)autoComplete.getSelectedItem().getValue();
}
else {
Bean tempCity = getMatch(autoComplete.getValue().toString());
if (tempCity != null) {
bean = tempCity;
}
}
}
}
Method setMatches
private void setMatches(ValueChangeEvent event) {
Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText)event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);
try {
int insert =
Collections.binarySearch(dictionary, searchWord, AutoCompleteDictionary.LABEL_COMPARATOR);
if (insert < 0) {
insert = Math.abs(insert) - 1;
}
for (int i = 0; i < maxMatches; i++) {
if ((insert + i) >= dictionary.size() || i >= maxMatches) {
break;
}
matchList.add(dictionary.get(insert + i));
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("Erorr finding autocomplete matches" + e.getMessage());
}
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
}
Update 2
Modified setMatches method
private void setMatches(ValueChangeEvent event) {
Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText) event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);
try {
for(int i = 0; i < dictionary.size(); i++) {
SelectItem s = (SelectItem)dictionary.get(i);
if(s.getLabel().startsWith(searchWord.toString())) {
matchList.add(s);
if(matchList.size() == maxMatches)
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("Erorr finding autocomplete matches" + e.getMessage());
}
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
}
You have to update the list of SelectItems. Instead of just odering the list you have to filter the list (or creating a new one which only contains the matches). The next time the autocomplete-list renders it will evaluate the bound list again.
The tutorial of icefaces has some sources attached (bottom). Take a look at AutoCompleteBean . The method updateList(ValueChangeEvent e) calls setMatches(e). Within this method the list is assigned with a new one.
// assign new matchList
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
This causes the ui component to show only items which match the input.
To sum it up: ice:selectInputList will always show the items contained in its list, so reduce the items in the list to show the relevant ones only.
Regards
Update
private void setMatches(ValueChangeEvent event) {
Object searchWord = event.getNewValue();
int maxMatches = ((SelectInputText)event.getComponent()).getRows();
List matchList = new ArrayList(maxMatches);
try {
for(int i = 0; i < dictionary.size(); i++) {
SelectItem s = dictionary.get(i);
if(s.getLabel().startsWith(searchWord)) {
matchList.add(s);
if(matchList.size() == maxMatches)
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("Erorr finding autocomplete matches" + e.getMessage());
}
if (this.matchesList != null) {
this.matchesList.clear();
this.matchesList = null;
}
this.matchesList = matchList;
}
// note: not optimized, just to explain how to do.
Update 2 (short version)
/**
* Fills the suggestionList with the given luceneResult.
*
* #param suggestionList The list to fill.
* #param luceneResult The previously computed luceneResult.
*/
private static void fillLookupSuggestionList(final List<SelectItem> suggestionList,
LuceneResult luceneResult)
{
suggestionList.clear();
String searchQuery = luceneResult.getLuceneResultConfig().getSearchQuery();
if (luceneResult.getResultSize() <= 0)
{
suggestionList.add(new SelectItem(null, BundleHelper.i18n(LuceneLookupController.BUNDLE,
LuceneLookupController.NO_ITEM_FOUND)));
}
else
{
List<LuceneResultEntry> results = luceneResult.getResult();
for (LuceneResultEntry entry : results)
{
suggestionList.add(new SelectItem(entry.getMetaInfo(),
entry.getInfo().getDescription()));
}
}
}