Is it possible to replace this:
if (archiveUnitEntity.getArchiveCaseEntityList() == null) {
archiveUnitEntity.setArchiveCaseEntityList(new ArrayList<ArchiveCaseEntity>());
}
archiveUnitEntity.getArchiveCaseEntityList().add(archiveCaseEntity);
This something like that:
ifListNullCreate(archiveUnitEntity.getArchiveCaseEntityList()).Add(archiveCaseEntity);
If you can change the method getArchiveCaseEntityList() then you could add that null check into the getter and update it there (or create another method if you need it to be null in some cases). If not, then you could create the method you want wherever you want/need.
But I don't think there is a built-in method to do that.
Here's one possible solution.
In the ArchiveUnitEntity class, declare the list like this, so that it's not null on creation.
private List<ArchiveCaseEntity> archiveCaseEntityList = new ArrayList<>();
You might also want to change the setter for that field, so that it can't get set to null.
public void setArchiveCaseEntityList(ArchiveCaseEntityList archiveCaseEntityList) {
this.archiveCaseEntityList = archiveCaseEntityList == null ? new ArrayList<ArchiveCaseEntity>() : archiveCaseEntityList;
}
It's better to initialize your archiveCaseEntityList attribute during the creation of the instance of archiveUnitEntity. Avoiding null object can simplify a lot of things :)
Directly when you declare your attribute :
private List<ArchiveCaseEntity> archiveCaseEntityList = new ArrayList<>();
or in constructor :
public ArchiveUnitEntity(){
this.archiveCaseEntityList = new ArrayList<>();
}
And finally, you could build a new method to manage ArchiveCaseEntity addition :
public void addArchiveCaseEntity(ArchiveCaseEntity entity){
this.archiveCaseEntityList.add(entity);
}
Related
I am writing a Unit Test for a class as follows:
#Test
void testCreateStackResources()
{
List<StackResource> stackResourceListExpected = new ArrayList<>();
StackResource stackResource = new StackResource();
stackResource.setLogicalResourceId("Sample-Logical-ID");
stackResourceListExpected.add(stackResource);
ListStackResourcesResult listStackResourcesResult = new ListStackResourcesResult();
StackResourceSummary stackResourceSummary = new StackResourceSummary();
stackResourceSummary.setLogicalResourceId("Sample-Logical-ID");
listStackResourcesResult.setStackResourceSummaries((Collection<StackResourceSummary>) stackResourceSummary); // Problem in this line
Mockito.when(amazonCloudFormation.listStackResources(Mockito.any(ListStackResourcesRequest.class))).thenReturn(listStackResourcesResult);
List<StackResource> stackResourceListResult = cloudFormationManager.createStackResources(Mockito.anyString());
Assert.assertEquals(stackResourceListExpected, stackResourceListResult);
}
Now, when I run this code, it gives me an error that I can't cast StackResourceSummary to a Collection in Java.
java.lang.ClassCastException: com.amazonaws.services.cloudformation.model.StackResourceSummary cannot be cast to java.util.Collection
On the other hand, if I make an array list before, add the object of StackResourceSummary to the list and then run the UT, it gives me the
objc[3648]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/bin/java (0x10d19c4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10ea194e0). One of the two will be used. Which one is undefined.
This is very weird behaviour. I don't know why can't I cast this to a collection? Please help. Thanks!
PS: There is a seperate class called ListStackResourcesResult which has a setter as follows:
public void setStackResourceSummaries(java.util.Collection<StackResourceSummary> stackResourceSummaries) {
if (stackResourceSummaries == null) {
this.stackResourceSummaries = null;
return;
}
this.stackResourceSummaries = new com.amazonaws.internal.SdkInternalList<StackResourceSummary>(stackResourceSummaries);
}
And I am trying to use this method above.
That is because StackResourceSummary does not extend or implement anything related to a collection.
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/cloudformation/model/StackResourceSummary.html
What you need to to is create a collection and add your instance of StackResourceSummary to it. For example like so:
List<StackResourceSummary> stackResourceSummaries = new ArrayList<StackResourceSummary>();
stackResourceSummaries.add(stackResourceSummary)
or maybe like so
Arrays.asList(stackResourceSummary)
or use a third party lib like guava collections.
Then you should use that collection as an argument.
listStackResourcesResult.setStackResourceSummaries(stackResourceSummaries); // Problem gone in this line
for a piece of homework, I have to set a variable. The set method given to me, converts that into "Optional". However, I have to store this variable in an ArrayList which doesn't allow Optional variables.How can I convert the variable so it is no longer Optional?
The set method:
public void setParentVertex(IVertex<T> parentVertex)
{
if(parentVertex == null)
this.parentVertex = Optional.empty();
else
this.parentVertex = Optional.of(parentVertex);
}
Where I'm trying to use it:
ArrayList<IVertex<T>> path = new ArrayList<IVertex<T>>();
IVertex<T> parent = current.getLabel().getParentVertex();
path.add(parent);
The error I keep receiving is: "Error: incompatible types: Optional> cannot be converted to IVertex" due to the line where I declare the variable "parent".
Thank you.
Here is the correct version
List<IVertex<T>> path = new ArrayList<IVertex<T>>();
current.getLabel().getParentVertex().ifPresent(path::add)
Also it would be good to rewrite setParentVertex function:
public void setParentVertex(IVertex<T> parentVertex) {
this.parentVertex = Optional.ofNullable(parentVertex);
}
I think you don't have to add it to your list, if there is no value. So just do
if(nameOfOptional.isPresent()){
list.add(nameOfOptional.get());
}
First, add a check to find the value is present or not (by calling isPresent()) and then if the value is present then add to your ArrayList path object as shown below:
ArrayList<IVertex<T>> path = new ArrayList<>();
Optional<IVertex<T>> parent = current.getLabel().getParentVertex();
if(parent.isPresent()) {
path.add(parent.get());
}
or the shorter form is shown below which uses ifPresent method:
ArrayList<IVertex<T>> path = new ArrayList<>();
Optional<IVertex<T>> parent = current.getLabel().getParentVertex();
parent.ifPresent(path::add);
Also, I suggest you have a look at the Optional API methods here.
As a side note, I recommend you to use diamond <> operator while declaring generic types (like shown above i.e., new ArrayList<>()) , so that your code will be less verbose.
I have the following code:
private Facility updateFacility(Facility newFacility, Facility oldFacility) {
if (newFacility.getCity() != null)
oldFacility.setCity(newFacility.getCity());
if (newFacility.getContactEmail() != null)
oldFacility.setContactEmail(newFacility.getContactEmail());
if (newFacility.getContactFax() != null)
oldFacility.setContactFax(newFacility.getContactFax());
if (newFacility.getContactName() != null)
oldFacility.setContactName(newFacility.getContactName());
// ......
}
There are around 14 such checks and assignments. That is, except for a few, I need to modify all the fields of the oldFacility object. I'm getting a cyclomatic complexity of this code 14, which is "greater than 10 authorized" as per SonarQube. Any ideas upon how to reduce the cyclomatic complexity?
At some point in your program, you will have to implement the logic:
If the new facility has a property defined, update the old facility accordingly
If not, do not override the previous value from the old facility.
Without having a global look at your project, what you can do is to move that logic inside the setters of each property:
public class Facility {
public void setSomething(String something) {
if (something != null) {
this.something = something;
}
}
}
This way, your update method would simply be:
private Facility updateFacility(Facility newFacility, Facility oldFacility) {
oldFacility.setSomething(newFacility.getSomething());
// etc for the rest
}
I think you can apply Builder Pattern to resolve the issue, it may help you remove the frustration in the loop of if statement. Please see this link for more detials
You can override hashCode and equals methods in Facility class and do as follows:
if(!newFacility.equals(oldFacility))
{
//only when something is changed in newFacility, this condition will be excecuted
oldFacility = newFacility;
}
return oldFacility;
//This is just and example, you can return newFacility directly
NOTE : You can include all params or only those which decide the uniqueness. Its up to you.
Hope this helps!
You could copy the fields for the oldFacility object that you don't want to modify to some other variables, then update the whole oldFacility object, and just replace the fields that you didn't want to change with the content stored in the other variables. i.e.
private Facility updateFacility(Facility newFacility, Facility oldFacility){
String contentNotToBeModified; // or whatever variable type
contentNotToBeModified = oldFacility.getCity();
// Do the same for all data that you want to keep
oldFacility = newFacility;
newFacility.setCity(contentNotToBeModified);
}
So copy the data that you want to keep out of oldFacility first, then substitute oldFacility for newFacility, and replace the required attributes of newFacility with the data from oldFacility.
The not null check seems pointless to me since the NullPointerException won't be thrown if you slightly modify your example like this:
private Facility updateFacility(Facility newFacility, Facility oldFacility) {
if (newFacility != null) {
oldFacility.setCity(newFacility.getCity());
oldFacility.setContactEmail(newFacility.getContactEmail());
oldFacility.setContactFax(newFacility.getContactFax());
oldFacility.setContactName(newFacility.getContactName());
...
}
This will assign null values to references which were referencing to nulls anyway and will not cause any issues.
Assuming you were doing something like newFacility.getCity().toString() then the checks would be useful.
You could use Java Reflection for avoiding that copy/paste/write-same-Problem:
public Facility updateFacility(Facility newFacility, Facility oldFacility)
{
String[] properties = {"City", "ContactEmail", "ContactFax", "ContactName"};
for(String prop : properties) {
try {
Method getter = Facility.class.getMethod("get"+prop);
Method setter = Facility.class.getMethod("set"+prop, getter.getReturnType());
Object newValue = getter.invoke(newFacility);
if (newValue != null)
setter.invoke(oldFacility, newValue);
} catch (NoSuchMethodException |
SecurityException |
IllegalAccessException |
InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
...
}
Now you can simple change the properties[] array when there are new properties in the Facility class which you want to update that way.
EDIT: If you use the return type of the getter method to find the setter method, it is not neccessary to assume that the properties of Facility are all of the same type.
CAVEATS: Be careful in method renaming! This code will lead to runtime errors if you rename or remove methods from the Facility class. If you have to possibility to change the code of the Facility class, you should consider using an annotation to indicate which properties should be updated.
With Deadbolt's module we can check the restrictedResource with a ressource name and parameters in the view.
For example in my view, I have it, and it works well:
#{deadbolt.restrictedResource resourceKeys:['Domain'] , resourceParameters:['domainid':domain.id]}
<li>${domain.title}</li>
#{/deadbolt.restrictedResource}
But in my controller, I just can check the ressource name but I don't find a way to check it in my RestrictedResourcesHandler passing the domainid with.
I am looking for a solution to do something like that:
#RestrictedResource(name = {"Domain"}, params = {domainid})
public static void showDomain(String domainid)
{
}
Thanks in advance
It's not possible to have dynamic information in an annotation, but you can use params to define the name of an incoming value in the request. However, this information isn't passed into the handler at the moment because it expects a map. While you can pass in a map of parameters from the restrictedResource tag, you can't do this from an annotation so an empty map is passed into the handler.
Your best approach here is to pull a well-known parameter name from the request object. I need to have a rethink about the best way to do this without breaking backwards compatibility.
Steve (author of Deadbolt)
I've found a way the solved the problem, not the best I think, but it is the Steve Chaloner's solution (Deadbolt's creator), and it works.
For example, if your Controller's method argument is named "id", and you want to check this id inside your checkAccess method :
// Controller's method :
#RestrictedResource(name = {"Domain"})
public static void showDomain(String id){}
Just check at the beginning of your checkAccess method the Map "resourceParameters" is empty, and use the request object to get the parameters:
public AccessResult checkAccess(List<String> resourceNames,
Map<String, String> resourceParameters)
{
Map<String, String> hashm = new HashMap<String,String>();
if(resourceParameters != null && !resourceParameters.isEmpty()){
hashm = resourceParameters;
}else if(Http.Request.current().routeArgs!= null && !Http.Request.current().routeArgs.isEmpty()){
hashm = Http.Request.current().routeArgs;
}
}
Then just have to foreach your hashmap inside your checkAccess method to get your Controller's method argument and check the Access as you wish.
for (Map.Entry<String,String> mp : hashm.entrySet())
{
// Get the id argument
if(mp.getKey().equals("id"))
{
// Do something with the value..
mp.getValue()
}
}
I was told it is not a good style to call potentially costly methods for boolean expressions (getSupercategories()).
private final SuperCategoriesResolver<ProductModel> catResolver = new SuperCategoriesResolver<ProductModel>() {
#Override
public Set<CategoryModel> getSuperCategories(final CategoryModel item) {
return item == null || item.getSupercategories() == null ? Collections.EMPTY_SET
: new LinkedHashSet<CategoryModel>(
item.getSupercategories());
}
};
As well that getSupercategories() is potentially dangerous since it's backed by a relation attribute which might not be coming from local data members (item is sent as a parameter to a public method in this class and after wards is sent to getSuperCategories() which is overriden in the same class when declaring catResolver).
Is this a better approach to tackle the argument above?
private final SuperCategoriesResolver<ProductModel> catResolver = new SuperCategoriesResolver<ProductModel>() {
#Override
public Set<CategoryModel> getSuperCategories(final ProductModel item) {
if (item != null) {
Set<CategoryModel> superCategories = (Set<CategoryModel>) item
.getSupercategories();
if (superCategories != null)
return superCategories;
}
return Collections.EMPTY_SET;
}
};
Where I first verify that item is not null. if it is, then a return empy_set if not then I called the costly method and get the collection and just if it is not null return the collection with elements.
Thank u very much for your advice.
It is likely to get more efficient to call getSupercategories() once instead of twice if it does any computation.
Do you need to return a copy of this set? You do in the first example but not the second.
Second approach is indeed faster because there is only one call to the getSupercategories method if item is not null. However, in your second approach, you no longer create a LinkedHashSet instance -- which means it will behave differently (though faster).
This sounds more like performance optimization as opposed to refactoring. Usually when you refactor something, there is a "factor" in there somwhere, that trims the code down by eliminating redundancies.
Nulls are your problem. Can you make a refactoring to push nulls away?
For example, you could refactor your code to make item.getSuperCategories never return null? Or do you need to distinguish between the empty set and null?
Similarly, why are you passing null into this method? If you can eliminate that scenario then the code just becomes a one liner.