I have a method which builds an object and returns it.
The object as UUID as one of its fields. While building the object, random UUID is generated. Here is the code:
public MetaData getMetaData(String id) {
return MetaData.newBuilder().setId(id)
.setCorrelationId(UUID.randomUUID().toString())
.setCreatedAt(now(UTC).format(ISO_ZONED_DATE_TIME))
.build();
}
Here is my test:
#Test
public void shouldVerifyIfTheMetaDataIsBuild() {
MetaData metaData = handler.getMetaData("1234");
assertThat(metaData.getId(), is("1234"));
assertThat(metaData.getCorrelationId(), isNotNull());
}
I'm just verifying if the correlationId is not null or not. Is there a better way to verify the UUID?
The only way to verify the current production code is to, yes, check that CorrelationId is not null. You could also check that the layout of the expected string matches a valid UUID string.
Of course, when you want to a bit of better checking, then you simply have to replace UUID.randomUUID().toString() with something that you can control.
For example you could create a UUIDGenerator interface, with a default method that creates a random UUID, as shown in your code. But in your test setup, you instead provide an implementation of that interface that returns a specific UUID.
Then your test code could know which UUID should be used, and assertThat(actualUuid, is(expectedUuid)).
I would change this line:
assertThat(metaData.getCorrelationId().toString(), isNotNull());
to the following:
assertThat(metaData.getCorrelationId(), isNotNull());
otherwise you would get a NullPointerException if metaData.getCorrelationId() returns null instead of an assertion failure.
Additionally, you could test if metaData.getCorrelationId() returns a string that represents a valid UUID, by trying to parse it:
try {
UUID.fromString(metaData.getCorrelationID());
} catch (IllegalArgumentException e) {
fail("Correlation ID is not a valid UUID: " + metaData.getCorrelationId());
}
When using a UUID, I check the String pattern using a regex.
assertTrue(id.matches(Pattern("([a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8})")))
This way I check if it is present and if the String is indeed a UUID as I had it happen that an unintended change put a space there which would pass in the assertNotNull solutions.
One more thing you can validate about UUID is it's length (as it is always 36 java.util.UUID.randomUUID().toString() length).
There will be a chance for detecting changes in implementation in future.
I added a UUID validator to Apache Commons Validator. It's not yet been merged, but you can vote for it here: https://github.com/apache/commons-validator/pull/68
As rightly said by #GhostCat, since we don't have control over UUID.randomUUID(), the only way would be to check if the UUID generated is not null. For that, you may use the code below:
assertNotNull(metaData.getCorrelationId());
Related
In the context of using the OWLAPI 4.0 API, this following line of code:
ontologyIRI = IRI.create(o.getOntologyID().getOntologyIRI().toString());
returns the following string :
"Optional.of(http://www.indytion.com/music/composition)".
What I need is the sole string "http://www.indytion.com/music/composition".
I tried to declare ontologyIRI as Optional and use .get() method, .orElse(), etc. to no avail. I still have the returned string that includes the 'optional.of()' part.
My question is : How could I get the internal string?
Thank you very much for your help.
Edit : The full code the method
private void LoadOntology(String ontologyPath)
{
OWLOntologyManager man = OWLManager.createOWLOntologyManager();
OWLOntology o;
File ontologyFile = new File(ontologyPath);
Optional<IRI> ontologyIRI;
try {
o = man.loadOntologyFromOntologyDocument(ontologyFile);
ontologyIRI = Optional.of(IRI.create(String.valueOf(o.getOntologyID().getOntologyIRI()).toString()));
System.out.println("Ontology IRI is: " + ontologyIRI.get());
} catch (OWLOntologyCreationException e) {
e.printStackTrace();
}
}
The System.out.println() returns exactly this string:
"Ontology IRI = Optional.of(http://www.indytion.com/music/composition)"
Use .get() instead of toString()
//Returns 'Optional[example]'
Optional.of("example").toString();
//Returns 'example'
Optional.of("example").get();
Short answer: Replace
Optional.of(IRI.create(String.valueOf(o.getOntologyID().getOntologyIRI()).toString()));
with
o.getOntologyID().getOntologyIRI().get();
Longer answer: you're doing an awful lot of back-and forth that's pointless at best and actively harmful in some cases:
In no particular order:
others have already commented that IRI instances are immutable, so creating a new one from an existing one is kind of pointless (if harmless).
calling Optional.of() if you don't intend to actually return an Optional is almost always a bad idea.
String.valueOf() is used to get a string-representation of some value and is usually most useful for debugging, but should not be relied on to fully round-trip everything about an object (the same applies to toString().
So basically what you're left with is this:
o.getOntologyID().getOntologyIRI() gives you an Optional<IRI>
you want an IRI.
Optional::get returns the value contained in the optional, if one exists, so you simply need to call get()
If, however the Optional is empty (i.e. there is no underlying value) then get() will throw a NoSuchElementException. This might or might not be what you want. To work around this either call isPresent() before calling get() to check if a value exists or use any of the multitude of other accessor methods, some of which have "built-in checks" in a way.
Finally, it seems that the problem was not the code itself. This is how the problem has been solved. But I don't understand why it has been solved :
I copy/paste (in the same file) the "shouldAddObjectPropertyAssertions()" example from OWLAPI4 examples -> This example code runs OK (but does not use the getOntologyID() method as I do).
Change SDKs to another minor version '1.8.0_61'
Change again with initial and desired SDK '1.8.0_131'
Invalidate caches and restart the IDE
Problem solved. The exactly same code :
ontologyIRI = o.getOntologyID().getOntologyIRI().get();
System.out.println("Ontology IRI is: " + ontologyIRI);
Now returns the expected string value : "http://www.indytion.com/music/composition" and not "Optional.of(http://www.indytion.com/music/composition)" anymore.
If someone can explain why it has been fixed, I would be very glad.
Thank you again for your help.
I am taking a JSON file as input for a class and parsing the values using gson through respective data classes.
I want to call a function that takes a String value as an argument.
The string value allowed is decided from the values parsed from JSON file. Can I somehow check for that string value passed to the function at compile-time & give an error at compile-time?
Or If I can allow only certain values in the argument for the function based on the values from JSON
Detailed Explanation of use case:
I am building a SDK in which a the person using sdk inputs json String. The json is standardised and is parsed in my code.
{
"name": "Test",
"objects": [
{
"name": "object1",
"type": "object1"
}
]
}
Here name values and other values may vary based on the input by the developer using it but key remains same. But we need to call a function using the value in objects name parameter.
fun testMethod(objectName:String)
So developer calls the testMethod as testMethod(object1).
I need to validate object1 parameter based on json but is there any way possible restricting the test method parameter to object1 only & give error at compile time if the developer calls testMethod(obj1)
Right now I parse JSON & have checks inside the testMethod()
Sure it's possible to do, but somehow in different way, that you described. First of all, as you already mentioned this behavior could be done easily. For this purpose we have Objects.requireNotNull() or Guava.Preconditions(). At the same way you can define you checking but this will work on runtime only.
To do in compile time, you need to create Annotation Preprocessor. The same, as did in different libraries, and one of them, could be Lombok, with their NotNull and Nullable. Android annotation just provide mark and bound for IDE warning, but in their case they adding NotNull checking and throw exception for every annotation usage during compile time.
It's not an easy way, but it's what you are looking for.
No, it's impossible check it in compiler time. It's string handling, as numeric calculation.
In my app, I convert string to JSON and JSON to string, passing class descriptor. My aim is record JSON string in a text file to load in SQLite database. This code I've run in my desktop computer not in Android.
data class calcDescr (
...
)
val calc = CalcDescr(...)
// toJson: internal Kotlin data to JSON
val content = Gson().toJson(calc)
//==================
// Testing validity
// ================
// fromJson: JSON to internal Kotlin data.
// It needs pass the class descriptor. Uses *Java* token, but it's *Kotlin*
var testModel = Gson().fromJson(content, CalcDescr::class.java)
// toJson: internal Kotlin data to JSON again
var contentAgain = Gson().toJson(testModel)
// shoul be equal!
if (content == contentAgain) println("***ok***")
In my file, I write the variable content in a file
I recently got a report that a few Google Analytics event category names were being recorded with an i character with out a dot on top.
Pageviews and events occurring twice, once without dots over the i.
I had to look to believe it. Sure enough, I had an event called favorite and there was a handful called favorıte. Copy and paste that weird character into a terminal or a monospace font just to see how weird it is. favorıte
My first suspicion is my code where I generate the strings for the category names using toString on an enum.
public enum AnalyticsEvent {
SCREEN_VIEW,
FAVORITE,
UN_FAVORITE,
CLICK_EVENT,
... reduced for brevity;
public String val() {
return this.toString().toLowerCase();
}
}
Example of how that enum is used:
#Override
public void logSearchTag(String type, String value) {
...
logGAEvent(AnalyticsEvent.SEARCH_TAG.val(), type, value);
}
private void logGAEvent(String category, String action, String label) {
... // mGATracker = instance of com.google.android.gms.analytics.Tracker;
mGATracker.send(addCustomDimensions(new HitBuilders.EventBuilder()
.setCategory(category)
.setAction(action)
.setLabel(label))
.build());
...
}
I am going to solve this by actually assigning a string to the enums and instead return that in the val() function.
Though, I am curious if anyone knows why on a small handful of devices Enum.toString returns the enum name with that weird character replacing the i. I mean small. 8 out 50,000 is the average. Or is it possible that assumption is wrong and the error is on analytics service end somewhere? Really highly doubt that.
The String#toLowerCase method uses the default locale of the system. This use locale specific characters such as ı instead of i. In order to fix this problem call toLowerCase with a locale:
String test = "testString";
test.toLowerCase(java.util.Locale.ENGLISH) // Or your preferred locale
We are creating a REST API for managing a resource. We are using Jersey framework.
Following is the structure of the JSON
cable {
"id": 1,
"name": "Cable 1",
"description": "Test Cable",
"Site": 4
}
The JSON should map to the below class.
public class CableDTO {
private Long id;
private String name;
private String description;
//private SiteDTO site;
private Long siteID;
.
.
.
// Getters ans Setters
}
Site is actually a reference object. The input and output JSON, requires the CableDTO to contain Site id instead of the entire Site object. We have assemblers which convert the DTO's to Domain objects and vice-versa.
The sample assembler code is as below:
public class CableAssembler {
//some code
public void fillDomain(Cable cable, CableDto dto){
if(dto.getId() != null) cable.setID(dto.getId());
if(dto.getSiteID() != null) cable.setSiteId(dto.getSiteId())
//some more code below
}
}
This assembler works well when a brand new POST HTTP method is called. If the SiteID is not set in the input json, the site is set to null and all is hunky dory. However, on a PUT HTTP call, if the SiteID is not set, the existing SiteID is over written to null. This is because the same assembler is used in both PUT and POST call. The assembler checks if the siteID set in the DTO is null. If it is null, the existing siteID is overwritten. The problem is, I am not able to distinguish between whether the null value in the SiteID is because the value was not sent or the SiteID was indeed deliberately set to null (which is possible {"siteID":null} )
Any pointers on how to solve this?
We use Jackson for serialization/de-serialization.
If I understood right your situation, my propositions are:
If you can, add a boolean field to JSON and DTO telling if the siteID was set and sent and check it in the assembler or other code;
Give the siteId another default value, different from null, like -1 or 0, if it's possible.
It seems that you use your PUT request like PATCH request. To use PUT request properly you should GET cable info, change some fields and PUT back. In this case your siteId field will remain unchanged.
I need to write something like this:
private Set processedLinks = new HashSet();
public boolean isProcessed(String url) throws MalformedURLException {
return processedLinks.contains(new URL(url));
}
This doesn't work, because created URL is another object than URL in collection. I need to compare match of host and file of created URL with URLs in HashSet. What is the best way?
I wanted to extend URL with my class and override equals(), but URL is final. So the second idea I have is to make something like URLHashSet extends HashSet and override contains method. But I'm not sure if it wouldn't have negative effect to performance, because that HashSet will contains tens of thousands elements.
Do you have please some idea how to resolve this? Thanks.
I'd recommend using URI instead of URL.
URL.equals should be avoided. From the docs you will see that it requires name resolution (which is a blocking operation) and is "is known to be inconsistent with virtual hosting in HTTP". URIs make more sense because you are not actually comparing physical locations, just the identifiers.
I don't want this to come off sounding harsh, but I think your understanding of equals/hashCode is flawed.
The URL should hash out and compare identically even though the object references are two separate objects.
I would try just a simple test of creating two separate URL objects with the same string URL value.
The following tests should give you your answer:
u1 == u2 => false
u1.equals(u2) => true
u2.equals(u1) => true
u1.hashCode() == u2.hashCode() => true
Unless my understanding of your problem is incorrect.
Try using the String representation of the URL object.
you can use composition instead of inheritance , like :
class MyUrl {
private Url url;
public boolean equals (MyUrl otherUrl) {
}
}
and make Set of MyUrl .