Creating & Setting a Map into context through SpringEl - spring-el

As SpringEl doc. indicates, there is el syntax for creating a list which then allows me setting it into the context as below:
List numbers = (List) parser.parseExpression("map['innermap']['newProperty']={1,2,3,4}").getValue(context);
However, I am not able to find a way of doing the same thing for Map nor I can find it in the document.
Is there a short hand way of creating a map and then setting it to context? if not, how can we go about it.
If possible a code snippet will be helpful.
Thanks in advance.

It's now possible (since 4.1, I think):
{key:value, key:value}
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html#expressions-inline-maps

No, it isn't possible yet: https://jira.spring.io/browse/SPR-9472
But you can do it with some util method, which should be registered as SpEL-function:
parser.parseExpression("#inlineMap('key1: value1, key2:' + value2)");
Where you have to parse the String arg to the Map.
UPDATE
Please, read this paragraph: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html#expressions-ref-functions.
From big height it should be like this:
public abstract class StringUtils {
public static Map<String, Object> inlineMap(String input) {
// Here is a code to parse 'input' string and build a Map
}
}
context.registerFunction("inlineMap",
StringUtils.class.getDeclaredMethod("inlineMap", new Class[] { String.class }));
parser.parseExpression("#inlineMap('key1: value1, key2:' + value2)")
.getValue(context, rootObject);

Related

FilterProxyListModel examples in CodenameOne

Since Codename One supports a subset of base Java Object Functionality, I can't use Vector.sort() to sort my data before adding it into a DefaultListModel. so Looking for other sorting options in Codename One, I found the FilterProxyListModel.
I can't find an example of how to properly initialize the FilterProxyListModel as it's using an interesting but tricky "Proxy" design pattern that I'm unfamiliar with. Here's how I've implemented it so far, but the component doesn't show any elements in the simulator when I do it this way. This is in the "initListModel..." method for my List from the GUI Builder:
protected boolean initListModelLearnableTopicsList(List cmp){
Vector learnableListModel = new Vector;
//omitting initialization of learnableListModel as a Vector of HashTables with key/value pairs to display
...
FilterProxyListModel<DefaultListModel> fpListModel = new FilterProxyListModel<DefaultListModel>(new DefaultListModel(learnableListModel)) {
#Override
protected int compare(Object a, Object b, boolean ascending) {
//details omitted... uses data in the LearnableListModel to provide sort order
}
#Override
protected boolean check(Object o, String str) {
//force all results to pass filter since original method fails when a Map object without a key of "name" is in the list
return true;
}
};
fpListModel.sort(true);
cmp.setModel(fpListModel);
}
Am I doing something wrong here? is there an example somewhere I should be using as a guide to doing this properly?
You can use Collections.sort(vector); the filter model is for list classes which we don't really recommend as much https://www.codenameone.com/blog/avoiding-lists.html

How to create a read-only array in java?

I want to get rid of clone() method.
For the below class sonar (static code check tool) was complaining that
I should not directly expose an internal array of the object as one can change the array after the method call which in turn changes the object's state. It suggested to do a clone() of that array before returning so that object's state is not changed.
Below is my class...
class DevicePlatformAggregator implements IPlatformListings{
private DevicePlatform[] platforms = null;
public DevicePlatform[] getAllPlatforms() throws DevicePlatformNotFoundException {
if (null != platforms) {
return platforms.clone();
}
List<DevicePlatform> platformlist = new ArrayList<DevicePlatform>();
..... // code that populates platformlist
platforms = platformlist.toArray(new DevicePlatform[platformlist.size()]);
return platforms;
}
}
However I don't think its good to clone as its unnecessary to duplicate the data.
There is nothing similar to Collections.unmodifiableList() for array
I can not change the return type of the method getAllPlatforms() to some
collection as it is an interface method
I am not a Java guru but I am pretty confident that you are out of luck here. There is no way to make a primitive array immutable apart from creating an array of 0 elements.
Making it final won't help cause only the reference pointing to it would be immutable.
As you already said the way to go in obtaining an unmodifiable list would be to use Collections as in the following example:
List<Integer> contentcannotbemodified= Collections.unmodifiableList(Arrays.asList(13,1,8,6));
Hope it helps.

iBatis unable to read property from Map when using isEqual

I'm seeing a very bizarre issue with iBatis when trying to read a property from a Java map using isEqual, but not with other iBatis operators. For example it is able to read the map properties fine when using isNotNull and iterate. The xml:
<isNotNull property="filterCriteria.account">
AND
id
<isEqual property="filterCriteria.account.meetsCriteria" compareValue="false">
NOT
</isEqual>
IN
(SELECT DISTINCT id
FROM account
WHERE some other criteria....
)
</isNotNull>
The 2 java classes we're using here:
public class SearchProfile {
private Map<String, SearchProfileCriteria> filterCriteria;
public SAOSearchProfile() {
filterCriteria = new HashMap<>();
}
public Map<String, SAOSearchProfileCriteria> getFilterCriteria() {
return filterCriteria;
}
public void setFilterCriteria(Map<String, SAOSearchProfileCriteriaBase> filterCriteria) {
this.filterCriteria = filterCriteria;
}
}
Above is the container object that is passed to iBatis for the querying, and below is the criteria object that will be the value of the map. In this example it is keyed with the String "account"
public class SearchProfileCriteria {
boolean meetsCriteria;
public String getCriteriaAsString() {
return StringUtils.getStringValueFromBoolean(meetsCriteria);
}
public boolean isMeetsCriteria() {
return meetsCriteria;
}
public void setMeetsCriteria(boolean meetsCriteria) {
this.meetsCriteria = meetsCriteria;
}
public String getSQLString(){
return meetsCriteria ? "" : "NOT";
}
}
And the exception:
Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'account' in class 'java.util.Map'; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
The getSQLString() method was my half baked attempt at a work around, the String gets escaped in the query and throws a syntax error.
When I remove the <isEqual> block the query executes find, which indicates it is able to read the "account" key when checking the to see if it is null. As I mentioned above, we're also able to use the map keys in <iterate> tags without issue. It seems <isEqual> and <isNotEqual> are the only tags causing issues. Does anyone have experience with this or know what may be going on?
Beware: Using isNotNull, isEqual, iterate is iBatis, they don't exist anymore in Mybatis, so referencing to Mybatis indifferently is confusing.
Reference documentation.
For your issue, how does it behave if replacing Map with a class (property will be known at compile time)?
Or try using <isPropertyAvailable>.
The work around could work with right syntax: $ instead of #: $filterCriteria.account.SQLString$ instead of #filterCriteria.account.SQLString#, then the value is just concatenated instead of bound as parameter.

New to AutoFixture trying to get my head around it and I can't see it helping me

Currently, I'm using custom made fake objects that behind the scenes use NSubstitute which creates the actual objects but it's becoming very hard to maintain as the project grows, so I'm trying to find alternatives and I'm hoping that AutoFixture is the right tool for the job.
I read the documentation and I'm struggling because there's very little to no documentation and I read most of the blog posts by Mark Seemann including the CheatSheet.
One of the things that I'm having hard time to grasp is how to create an object with a constructor that have parameters, in my case I need to pass argument to CsEmbeddedRazorViewEngine as well as HttpRequestBase to ControllerContext.
The way I see it is that I need to create a fake objects and finally create a customization object that injects them to
I also looked into NBuilder it seems slightly more trivial to pass arguments there but I've heard good things about AutoFixture and I would like to give it a try. :)
I'm trying to reduce the amount of fake objects I have so here is a real test, how can I do the same thing with AutoFixture?
[Theory,
InlineData("en-US"),
InlineData("en-us"),
InlineData("en")]
public void Should_return_the_default_path_of_the_view_for_enUS(string language)
{
// Arrange
const string EXPECTED_VIEW_PATH = "~/MyAssemblyName/Views/Home/Index.cshtml";
CsEmbeddedRazorViewEngine engine = CsEmbeddedRazorViewEngineFactory.Create(ASSEMBLY_NAME, VIEW_PATH, string.Empty);
string[] userLanguage = { language };
HttpRequestBase request = FakeHttpRequestFactory.Create(userLanguage);
ControllerContext controllerContext = FakeControllerContextFactory.Create(request);
// Act
ViewEngineResult result = engine.FindPartialView(controllerContext, VIEW_NAME, false);
// Assert
RazorView razorView = (RazorView)result.View;
string actualViewPath = razorView.ViewPath;
actualViewPath.Should().Be(EXPECTED_VIEW_PATH);
}
P.S. I'm using xUnit as my testing framework and NSubstitute as my mocking framework should I install both AutoFixture.Xunit and AutoFixture.AutoNSubstitute?
UPDATE: After learning more and more about it I guess it is not the right tool for the job because I tried to replace my test doubles factories with AutoFixture rather than setting up my SUT with it.
Due to odd reason I thought it's doing the same thing NBuilder is doing and from what I can see they are very different tools.
So after some thinking I think I'll go and change the methods I have on my test doubles factories to objects then use AutoFixture to create my SUT and inject my test doubles to it.
Note: I don't have the source code for the CsEmbeddedRazorViewEngine type and all the other custom types.
Here is how it could be written with AutoFixture:
[Theory]
[InlineAutoWebData("en-US", "about", "~/MyAssemblyName/Views/Home/Index.cshtml")]
[InlineAutoWebData("en-US", "other", "~/MyAssemblyName/Views/Home/Index.cshtml")]
public void Should_return_the_default_path_of_the_view_for_enUS(
string language,
string viewName,
string expected,
ControllerContext controllerContext,
CsEmbeddedRazorViewEngine sut)
{
var result = sut.FindPartialView(controllerContext, viewName, false);
var actual = ((RazorView)result.View).ViewPath;
actual.Should().Be(expected);
}
How it works:
It uses AutoFixture itself together with it's glue libraries for xUnit.net and NSubstitute:
PM> Install-Package AutoFixture.Xunit
PM> Install-Package AutoFixture.AutoNSubstitute
With InlineAutoWebData you actually combine inline values and auto-generated data values by AutoFixture – also including Auto-Mocking with NSubstitute.
internal class InlineAutoWebDataAttribute : CompositeDataAttribute
{
internal InlineAutoWebDataAttribute(params object[] values)
: base(
new InlineDataAttribute(values),
new CompositeDataAttribute(
new AutoDataAttribute(
new Fixture().Customize(
new WebModelCustomization()))))
{
}
}
Remarks:
You could actually replace the WebModelCustomization customization above with AutoNSubstituteCustomization and it could work.
However, assuming that you are using ASP.NET MVC 4, you need to customize the Fixture instance with:
internal class WebModelCustomization : CompositeCustomization
{
internal WebModelCustomization()
: base(
new MvcCustomization(),
new AutoNSubstituteCustomization())
{
}
private class MvcCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<ControllerContext>(c => c
.Without(x => x.DisplayMode));
// Customize the CsEmbeddedRazorViewEngine type here.
}
}
}
Further reading:
Encapsulating AutoFixture Customizations
AutoData Theories with AutoFixture
I ended up doing this.
[Theory,
InlineData("en-US", "Index", "~/MyAssemblyName/Views/Home/Index.cshtml"),
InlineData("en-us", "Index", "~/MyAssemblyName/Views/Home/Index.cshtml"),
InlineData("en", "Index", "~/MyAssemblyName/Views/Home/Index.cshtml")]
public void Should_return_the_default_path_of_the_view(string language, string viewName, string expected)
{
// Arrange
CsEmbeddedRazorViewEngine engine = new CsEmbeddedRazorViewEngineFixture();
ControllerContext controllerContext = FakeControllerContextBuilder.WithLanguage(language).Build();
// Act
ViewEngineResult result = engine.FindPartialView(controllerContext, viewName, false);
// Assert
string actualViewPath = ((RazorView)result.View).ViewPath;
actualViewPath.Should().Be(expected);
}
I encapsulated the details to setup my SUT into a fixture and used the builder pattern to handle my fakes, I think that it's readable and pretty straightforward now.
While AutoFixture looks pretty cool, the learning curve seems long and I will need to invest enough time to understand it, for now, I want to clean-up my unit tests and make them more readable. :)

Convert String into an object instance name

I'm trying to turn an string into an instance name.
stage.focus = ["box_"+[i+1]];
this gives me back = box_2;
but I need it to be an object not a string.
In as2 I could use eval. How do I do it in as3?
The correct syntax is:
this["box_"+(i+1)]
For example if you would like to call the function "start" in your main class, you'd do it this way:
this["start"]();
Same thing goes for variables. Since all classes are a subclass of Object you can retrieve their variables like you would with an ordinary object. A class like this:
package{
import flash.display.Sprite;
public class Main extends Sprite{
public var button:Sprite;
public function Main(){
trace(this["button"]);
}
}
}
Would output:
[object Sprite]
If you want to access a member of the current class, the answers already given will work. But if the instance you are looking isn't part of the class, you are out of luck.
For example:
private function foo():void {
var box_2:Sprite;
trace(this["box_"+(i+1)]);
}
Won't work, because box_2 isn't a part of the class. In that case, it is highly recommended to use an array.
If you want to access a DisplayObject (for example, a Sprite or a MovieClip) you also can use getChildByName. But in that case, box_2 will be the name of the object, instead of the name of the variable. You set the name like
var box:Sprite;
box.name = "box_2";
But again, I recommend an array.

Resources