Processing: manipulate variables by string names - java

I am importing a .txt file to use to run parts of my program. A certain part needs to manipulate boolean variables. However, I am using loadStrings() to interpret the text into Strings, with the individual lines called lines[]. I have a variable's name as a String and must reference the variable itself. Unfortunately, I have been unable to figure out how to do this.
boolean choice1 = false;
// lines[counter+2] is "choice1"
if (lines[counter+2] = false) {
println("statement is false");
counter += 4;
}
Obviously, the above statement doesn't work, nor does:
if (boolean(lines[counter+2]) = false) {
as it errors.
Also,
if (boolean(lines[counter+2]) == false) {
is not a possible solution as any word other than "true" when used in boolean() is false, so the above gives a false positive (pardon the pun).
If there is a solution to the same problem in java coding, I would be happy to see that as well.
P.S. If you have a solution, is there a way to not just reference the variable by its name, but also to change it? For example:
boolean(lines[counter+2]) = false;
or
lines[counter+2] = false;
obviously, the above are incorrect, but that idea.

You can't do that.
You could use a HashMap of String values to Boolean values though:
HashMap<String, Boolean> variableMap = new HashMap<String, Boolean>();
variableMap.put("myVariable", true); //set the value
boolean check = variableMap.get("myVariable"); //get the value
println(check);
variableMap.put("myVariable", false); //change the value
boolean checkAgain = variableMap.get("myVariable"); //get the new value
println(checkAgain);
More info can be found in the Processing reference.

Related

Optional tags within XML document?

I'm working on a missile-combat oriented game written in java that reads missile types with settings from an XML document. Each missile has many different parameters that can clog up the XML sometimes and make it hard to handle each missile type. What I am wondering is if it would be possible to code the XML parsing section of the code so that I can put in only the options that will be different from a default value. For example, one of the parameters is "nuclear," which can be true or false to indicate a nuclear missile. Would it be possible to write the code so that if is not present, it defaults to "false?"
Here is a missile type in the XML:
<MissileType ID="1" Name="Tomahawk">
<AssetID>15</AssetID>
<Purchasable>true</Purchasable>
<SpeedIndex>1</SpeedIndex>
<MissileCost>550</MissileCost>
<BlastRadiusIndex>2</BlastRadiusIndex>
<RangeIndex>3</RangeIndex>
<MaxDamageIndex>3</MaxDamageIndex>
<Nuclear>false</Nuclear>
<Tracking>true</Tracking>
<ECM>true</ECM>
</MissileType>```
Here is the code that parses the missile type:
for(int i = 0; i < ndeMissileTypes.getLength(); i++)
{
try
{
Element ndeMissileType = (Element)ndeMissileTypes.item(i);
byte cID = GetByteAttribute(ndeMissileType, XMLDefs.ID);
String strName = GetStringAttribute(ndeMissileType, XMLDefs.NAME);
int lAssetID = GetIntElement(ndeMissileType, XMLDefs.ASSET_ID);
boolean bPurchasable = GetBooleanElement(ndeMissileType, XMLDefs.PURCHASABLE);
byte cSpeedIndex = GetByteElement(ndeMissileType, XMLDefs.SPEED_INDEX);
int cMissileCost = GetIntElement(ndeMissileType, XMLDefs.MISSILE_COST);
byte cBlastRadiusIndex = GetByteElement(ndeMissileType, XMLDefs.BLAST_RADIUS_INDEX);
byte cRangeIndex = GetByteElement(ndeMissileType, XMLDefs.RANGE_INDEX);
byte cMaxDamageIndex = GetByteElement(ndeMissileType, XMLDefs.MAX_DAMAGE_INDEX);
boolean bNuclear = GetBooleanElement(ndeMissileType, XMLDefs.NUCLEAR);
boolean bTracking = GetBooleanElement(ndeMissileType, XMLDefs.TRACKING);
boolean bECM = GetBooleanElement(ndeMissileType, XMLDefs.ECM);
config.AddMissileType(cID, new MissileType(cID, bPurchasable, strName, lAssetID, bNuclear, bTracking, bECM, cSpeedIndex, cMissileCost, cRangeIndex, cBlastRadiusIndex, cMaxDamageIndex));
}
catch(Exception ex)
{
listener.LoadError(String.format("Error loading missile type at index %d: %s.", i, ex.getMessage()));
}
}
I would like it so that I can leave out lines from <MissileType> and have it return a default value for that position. For example, have a missile type that looks like this:
<MissileType ID="1" Name="Tomahawk">
<AssetID>15</AssetID>
<Purchasable>true</Purchasable>
<SpeedIndex>1</SpeedIndex>
<MissileCost>550</MissileCost>
<BlastRadiusIndex>2</BlastRadiusIndex>
<RangeIndex>3</RangeIndex>
<MaxDamageIndex>3</MaxDamageIndex>
</MissileType>
Which would return false for the missing boolean values at the end, essentially allowing me to only input the tags that are relevant to this particular missile type.
Of course you can. I can't see what your problem is. Just write
boolean bPurchasable = getBooleanElement(ndeMissileType, XMLDefs.PURCHASABLE, false);
where the 3-argument method is defined as
public boolean getBooleanElement(Element parent, QName name, boolean default) {
return parent.hasChild(name) ? GetBooleanElement(parent, name) : default
}
(Treat this as pseudo-code, because I don't know what API you are actually using. Note Java method names conventionally use an initial lower-case letter.)

How to store checkbox options to use in other classes?

Im using a method in my FXMLController to check if radio buttons are selected and storing them in a bollean array. I then will be calling this method in another class to get the boolean values to see which are selected to perform perfrom different actions using if statements accordingly.
public boolean[] GetSelectedOption() {
boolean[] OptionsValue = new boolean[2];
OptionsValue[0] = StripHtmlOption.isSelected();
OptionsValue[1] = StripHtmlOption.isSelected();
return OptionsValue;
}
Is this the right way of storing checkbox/radiobutton options? Is there a better way of doing this? As I can imagine this isn't very object orientated? Im a java beginner.
Here is the code where im trying to call the options/boolean values in another class. This code doesnt work though.
public String StripHtml(String html, String DomainName) {
FXMLController FetchOptions = new FXMLController();
boolean[] OptionsValue = FetchOptions.GetSelectedOption();
OptionsValue[0] = StripHtmlvalue;
OptionsValue[1] = = StripLinkValue;
if (Boolean.TRUE.equals(StripHtmlvalue)) {
System.out.println("Some code will go here");
} else {
}
return Stringyettobemade;
}
OptionsValue[0] = StripHtmlvalue;
OptionsValue[1] = = StripLinkValue;
At first please use lower case variable names.
At seccond why do you overwrite the values?
I think what you want is to GET the values so the right code will be:
StripHtmlvalue = optionValue[0];
and what should this do : = =?
This should work
boolean[] optionsValue ={stripHtmlvalue.isSelected(),stripLinkValue.isSelected()};

Best practice for variable saving

There are two code code 1:
if(isApplicable() || isGood()) {
//something
}
private boolean isApplicable() {
}
private boolean isGood() {
}
Code 2:
boolean applicable = isApplicable();
boolean good = isGood();
if(applicable || good) {
//something
}
private boolean isApplicable() {
}
private boolean isGood() {
}
Which of the the approach is good java practice ?
To me code1 seams more clean and code 2 seams to have extra code. code2 can make remote debugging easy.
To generalise your question, you're asking about the two forms:
// local variable form
Foo foo = methodReturningFoo();
Bar bar = methodTakingFoo(foo);
// inlined form
Bar bar = methodTakingFoo(methodReturningFoo());
Most modern IDEs have a shortcut to refactor between these at a keystroke: "inline" and "extract local variable". The fact that both refactorings exist is an indicator that both are appropriate, in different circumstances.
Inlining to a single statement makes the code more compact and sometimes more readable. You can see everything that's happening without having to read up to find out where a variable was set.
Here's a good candidate for inlining:
String name = customer.getName();
String greeting = createGreeting(name);
// ... becomes ...
String greeting = createGreeting(customer.getName());
Extracting a local variable turns what may be a long statement into two (or more) shorter statements. It may also allow you to re-use a value rather than calculate it twice.
Here's an example where we just break a statement into smaller chunks.
String greeting = createGreeting(greetingFactory.get(customer.getTitle()), customer.getName());
// ... becomes ...
Title title = customer.getTitle();
String name = customer.getName();
String greeting = createGreeting(greetingFactory.get(title), name));
... here's an example where we reuse a calculated value.
// doing the work twice
CustomerCategory category = findCategory(totalOrderValues(
customer.getOrders(currentMonth)));
List<Promotion> eligiblePromotions = findEligiblePromotions(totalOrderValues(
customer.getOrders(currentMonth)));
// ... becomes ...
BigInteger totalOrderValues = totalOrderValues(
customer.getOrders(currentMonth))
CustomerCategory category = findCategory(totalOrderValues);
List<Promotion> eligiblePromotions = findEligiblePromotions(totalOrderValues);
Generally, prefer the inlined version, until you see that the line is too long and complicated. Then extract a local variable (or extract a method) to make it neater. If it makes sense to store a value to avoid repeating an expensive calculation, then do so.

How to implement this property file?

I have this piece of data (this is just one part of one line of the whole file):
000000055555444444******4444 YY
I implemented this CSV config file to be able to read each part of the data and parse it:
128-12,140-22,YY
The first pair (128-12) represent at what position in the line to start reading and then the amount of characters to read, that first pair is for the account number.
The second pair if for the card number.
And the thir parameter is for the registry name.
Anyways, what I do is String.split(","), and then assign the array[0] as the account number and so on.
But I want to change that CSV config file to a Property file, but I'm not sure of how to implement that solution, if I use a Properties file I'd have to add a bunch of if/then in order to properly map my values, here's what I'm thinking of doing:
Property cfg = new Property();
cfg.put("fieldName", "accountNumber");
cfg.put("startPosition", "128");
cfg.put("length", "12");
But I'd have to say if("fieldName".equals("accountNumber")) then assign accountNumber; is there a way to implement this in such a way that I could avoid implementing all this decisions? right now with my solution I don't have to use ifs, I only say accountNumber = array[0]; and that's it, but I don't think that's a good solution and I think that using Property would be more elegant or efficient
EDIT:
This probably needs some more clarification, this data I'm showing is part of a parsing program that I'm currently doing for a client; the data holds information for many many of their customers and I have to parse a huge mess of data that I receive from them, into something more readable in order to convert it to a PDF file, so far the program is under production but I'm trying to refactor it a little bit. All the customer's information is saved into different Registry classes, each class having it's own set of fields with unique information, lets say that this is what RegistryYY would look like:
class RegistryYY extends Registry{
String name;
String lastName;
PhysicalAddress address;
public RegistryYY(String dataFromFile) {
}
}
I want to implement the Property solution, because in that way, I could make the Property for parsing the file, or interpreting the data correctly to be owned by each Registry class, I mean, a Registry should know what data it needs from the data received from the file right?, I think that if I do it that way, I could make each Registry an Observer and they would decide if the current line read from the file belongs to them by checking the registry name stored in the current line and then they'd return an initialized Registry to the calling object which only cares about receiving and storing a Registry class.
EDIT 2:
I created this function to return the value stored in each line's position:
public static String getField(String fieldParams, String rawData){
// splits the field
String[] fields = fieldParams.split("-");
int fieldStart = Integer.parseInt(fields[0]); // get initial position of the field
int fieldLen = Integer.parseInt(fields[1]); // get length of field
// gets field value
String fieldValue = FieldParser.getStringValue(rawData, fieldStart, fieldLen);
return fieldValue;
}
Which works with the CSV file, I'd like to change the implementation to work with the Property file instead.
Is there any reason why you need to have the record layout exposed to the outside world ? does it need to be configurable ?
I think your proposed approached of using the Property file is better than your current approach of using the CSV file since it is more descriptive and meaningful. I would just add a "type" attribute to your Property definition as well to enforce your conversion i.e. for Numeric/String/Date/Boolean.
I wouldnt use an "if" statement to process your property file. You can load all the properties into an Array at the beginning and then iterate around the array for each line of your data file and process that section accordingly something like pseudo code below,
for each loop of data-file{
SomeClass myClass = myClassBuilder(data-file-line)
}
myClassBuilder SomeClass (String data-file-line){
Map<column, value> result = new HashMap<>
for each attribute of property-file-list{
switch attribute_type {
Integer:
result.put(fieldname, makeInteger(data-file-line, property_attribute)
Date:
result.put(fieldname, makeDate(data-file-line, property_attribute)
Boolean :
result.put(fieldname, makeBoolean(data-file-line, property_attribute)
String :
result.put(fieldname, makeBoolean(data-file-line, property_attribute)
------- etc
}
}
return new SomeClass(result)
}
}
If your record layout doesnt need to be configurable then you could do all the conversion inside your Java application only and not even use a Property file.
If you could get your data in XML format then you could use the JAXB framework and simply have your data definition in an XML file.
First of all, thanks to the guys who helped me, #robbie70, #RC. and #VinceEmigh.
I used YAML to parse a file called "test.yml" with the following information in it:
statement:
- fieldName: accountNumber
startPosition: 128
length: 12
- fieldName: cardNumber
startPosition: 140
length: 22
- fieldName: registryName
startPosition: 162
length: 2
This is what I made:
// Start of main
String fileValue = "0222000000002222F 00000000000111110001000000099999444444******4444 YY";
YamlReader reader = new YamlReader(new FileReader("test.yml"));
Object object = reader.read();
System.out.println(object);
Map map = (Map) object;
List list = (List) map.get("statement");
for(int i = 0; i < list.size(); i++) {
Map map2 = (Map) list.get(i);
System.out.println("Value: " + foo(map2, fileValue));
}
}
// End of main
public static String foo(Map map, String source) {
int startPos = Integer.parseInt((String) map.get("startPosition"));
int length = Integer.parseInt((String) map.get("length"));
return getField(startPos, length, source);
}
public static String getField(int start, int length, String source) {
return source.substring(start, start+length);
}
It correctly displays the output:
Value: 000000099999
Value: 444444******4444
Value: YY
I know that maybe the config file has some lists and other unnecessary values and what nots, and that maybe the program needs a little improvement, but I think that I can take it from here and implement what I had in mind.
EDIT:
I made this other one, using Apache Commons, this is what I have in the configuration property file:
#properties defining the statement file
#properties for account number
statement.accountNumber.startPosition = 128
statement.accountNumber.length = 12
statement.account.rules = ${statement.accountNumber.startPosition} ${statement.accountNumber.length}
#properties for card number
statement.cardNumber.startPosition = 140
statement.cardNumber.length = 22
statement.card.rules = ${statement.cardNumber.startPosition} ${statement.cardNumber.length}
#properties for registry name
statement.registryName.startPosition = 162
statement.registryName.length = 2
statement.registry.rules = ${statement.registryName.startPosition} ${statement.registryName.length}
And this is how I read it:
// Inside Main
String valorLeido = "0713000000007451D 00000000000111110001000000099999444444******4444 YY";
Parameters params = new Parameters();
FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
.configure(params.properties()
.setFileName("config.properties"));
try {
Configuration config = builder.getConfiguration();
Iterator<String> keys = config.getKeys();
String account = getValue(getRules(config, "statement.account.rules"), valorLeido);
String cardNumber = getValue(getRules(config, "statement.card.rules"), valorLeido);
String registryName = getValue(getRules(config, "statement.registry.rules"), valorLeido);
} catch (org.apache.commons.configuration2.ex.ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// End of Main
public static String getRules(Configuration config, String rules) {
return config.getString(rules);
}
public static String getValue(String rules, String source) {
String[] tokens = rules.split(" ");
int startPos = Integer.parseInt(tokens[0]);
int length = Integer.parseInt(tokens[1]);
return getField(startPos, length, source);
}
I'm not entirely sure, I think that with the YAML file it looks simpler, but I really like the control I get with the Apache Commons Config, since I can pass around the Configuration object to each registry, and the registry knows what "rules" it wants to get, let's say that the Registry class only cares about "statement.registry.rules" and that's it, with the YAML option I'm not entirely sure of how to do that yet, maybe I'll need to experiment with both options a little bit more, but I like where this is going.
PS:
That weird value I used in fileValue is what I'm dealing with, now add nearly 1,000 characters to the length of the line and you'll understand why I want to have a config file for parsing it (don't ask why....clients be crazy)

How to compare a hashSet within a foreach loop iterating through another hashSet Java

I'm running a test to see if the values I've inputed into a file are the same values I generate from my API. So I have actual values which are generated from my API and I have another list of expected values. The problem I have is that I am not able to make apple to apple comparisons.
Example:
Actual = {red, bleu, yellow, purple}
expected = {bleu, red, purple, yellow}
failure: red != bleu, bleu != red, yellow != purple, purple != yellow
I'm not sure how else to better describe what I'm saying other than showing you my code.
Here is my code:
TreeSet<String> hashSet = (TreeSet<String>) calcGraph.getInputs();
boolean success = true;
String error="";
for(String xpath : hashSet) {
String actual = someApi(response, expression, xpath);
for ( String values : data.getDataOutputs().keySet() ) {
String expected = data.getDataOutputs().get(expectedXpath);
if ( !expected.equals(actual)) {
error+= "\nExpected : " + expected +"\nActual: " +actual+"\n";
success = false;
} if ( !success ) Assert.fail(error);
}
}
How can I compare these lists within 1 foreach loop or equivalent? Any help or assistance would be appreciated.
Edit:
Iterator<String> expectation = expectedList.iterator();
Iterator<String> actuation = actualList.iterator();
while((expectation.hasNext()) && (actuation.hasNext())) {
String exp = expectation.next();
String act = actuation.next();
logger.info("Expected: "+exp);
logger.info("Actual: "+act);
// Validation check
if ( !exp.equals(act)) {
error+= "\nExpected : " + exp +"\nActual: " +act+"\n";
success = false;
} if ( !success ) Assert.fail(error);
}
Order matters, so this will fail...
The question is just so weird. In the title you said HashSet vs HashSet comparison, and in the content you are using TreeSet.
From the question, it seems that you have a Set of actual results, and you want to compare against a Set of expected result, regardless of the iteration order, am I right?
Using contains is surely wrong, as well as using iterator to do comparison.
The solution is in fact straight-forward. From javadoc of Set:
boolean equals(Object o)
Compares the specified object with this set for equality. Returns true
if the specified object is also a set, the two sets have the same
size, and every member of the specified set is contained in this set
(or equivalently, every member of this set is contained in the
specified set). This definition ensures that the equals method works
properly across different implementations of the set interface.
What you need to do is simply
expectedResultSet.equals(actaulResultSet)
You can use
Set.contains(value)
to check if an actual value is in expected value, you only need one for loop to achieve this
See this
http://docs.oracle.com/javase/7/docs/api/java/util/Set.html#contains(java.lang.Object)

Categories

Resources