Cant get Multiple Nodes in AEM 6.1 - content-management-system

We have recently upgraded from AEM 5.6.1 to AEM 6.1 and our certain piece code given below has suddenly stopped working. In brief, we have been using the Node API to get child nodes of a particular node and then processing on it, but in AEM 6.1, it seems getNodes() method returns nothing and only getNode() seem to work. Has anyone else also faced the same and have any solution for it?
if (jobAdNode.hasNode(PARSYS_NODE_REL_PATH)) {
Node parsysNode = jobAdNode.getNode(PARSYS_NODE_REL_PATH);
NodeIterator textNodeItr = parsysNode.getNodes("text"); // RETURNS NOTHING
Node textNode1 = parsysNode.getNode("text"); // RETURN THE EXISTING TEXT NODE
if (textNodeItr.getSize() > 0) {
Node textNode = textNodeItr.nextNode();
if (textNode.hasProperty(TEXT_PROP)) {
resDescription.append(textNode.getProperty(TEXT_PROP).getString());
}
}
}

Okay, so after a lot of hit and trials, I have located the issue and would like to post here, in case anyone else faces the same. In the code that I posted above, the culprit is this line:
if (textNodeItr.getSize() > 0)
The parsysNode.getNodes("text"), method returns an iterator of nodes having the child nodes, however the getSize method still returns -1 and hence it looks like that no nodes are being returned. Look at the documentation of getSize() method here! , which says that the getSize method may not return the size in all implementations.
I solved the issue by using hasNext() which is mostly used.

Related

Javascript DOM addressing into a sub-window DOM element

Given this screenshot of a Firefox DOM rendering, I'm interested in reading that highlighted element down a ways there and writing to the "hidden" attribute 3 lines above it. I don't know the Javascript hierarchy nomenclature to traverse through that index "0" subwindow that shows in the first line under window indexed "3" which is the root context of my code's hierarchy. That innerText element I'm after does not appear anywhere else in the DOM, at least that I can find...and I've looked and looked for it elsewhere.
Just looking at this DOM, I would say I could address that info as follows: Window[3].Window[0].contentDocument.children[0].innerText (no body, interestingly enough).
How this DOM came about is a little strange in that Window[0] is generated by the following code snippet located inside an onload event. It makes a soft EMBED element, so that Window[0] and everything inside is transient. FWIW, the EMBED element is simply a way for the script to offload the task of asynchronously pulling in the next .mp4 file name from the server while the previous .mp4 is playing so it will be ready instantly onended; no blocking necessary to get it.
if (elmnt.contentDocument.body.children[1] == 'undefined' || elmnt.contentDocument.body.children[1] == null)
{
var mbed = document.createElement("EMBED");
var attsrc = document.createAttribute("src")
mbed.setAttributeNode(attsrc);
var atttyp = document.createAttribute("type")
mbed.setAttributeNode(atttyp);
var attwid = document.createAttribute("width")
mbed.setAttributeNode(attwid);
var atthei = document.createAttribute("height")
mbed.setAttributeNode(atthei);
elmnt.contentDocument.body.appendChild(mbed);
}
elmnt.contentDocument.body.children[1].src=elmnt.contentDocument.body.children[0].currentSrc + '\?nextbymodifiedtime'
elmnt.contentDocument.body.children[1].type='text/plain'
I know better than to think Window[3].Window[0]...... is valid. Can anyone throw me a clue how to address the DOM steps into the contentDocument of that Window[0]? Several more of those soft Windows from soft EMBED elements will eventually exist as I develop the code, so keep that in mind. Thank you!
elmnt.contentWindow[0].document.children[0].innerText does the trick

MRTK V2 - Enable/Disable Spatial Mapping at Runtime

I know that this question has already been asked here twice, but the answers did not fix my problem. I need to enable spatial mapping on runtime. After scanning my environment I want to disable it, or hide at least the visualization of polygons, so I can save some fps. But by disabling spatial mapping I still want to have the colliders of my environment.
What I tried:
1. This example from this post did nothing.
if (disable){
// disable
MixedRealityToolkit.SpatialAwarenessSystem.Disable();
}
else
{
// enable
MixedRealityToolkit.SpatialAwarenessSystem.Enable()
}
2. Trying to disable the visualization gives me every time a nullreference. I guess GetObservers is giving null back or maybe meshOserver is null:
foreach(var observer in MixedRealityToolkit.SpatialAwarenessSystem.GetObservers())
{
var meshObserver = observer as IMixedRealitySpatialAwarenessMeshObserver;
if (meshObserver != null)
{
meshObserver.DisplayOption = SpatialAwarenessMeshDisplayOptions.None;
}
}
3. The example given by mrtk in there SpatialAwarenessMeshDemo scene, shows how to start and stop the observer. By starting everything starts fine but after suspending and clearing the observers the whole spatial map disappears, so my cursor does not align to my environment. So this is not what I need.
SpatialAwarenessSystem.ResumeObservers(); //start
SpatialAwarenessSystem.SuspendObservers();//stop
SpatialAwarenessSystem.ClearObservations();
What I have right now:
My Spatial Awareness Profile looks like this:
My code starts the spatial mapping with ResumeObservers, the foreach-loop gives me a nullreference and SuspendObserver is comment out, because it disables the whole spatial map thing:
if (_isObserverRunning)
{
foreach (var observer in SpatialAwarenessSystem.GetObservers())
{
var meshObserver = observer as IMixedRealitySpatialAwarenessMeshObserver;
if (meshObserver != null)
{
meshObserver.DisplayOption = SpatialAwarenessMeshDisplayOptions.None;
}
}
//SpatialAwarenessSystem.SuspendObservers();
//SpatialAwarenessSystem.ClearObservations();
_isObserverRunning = false;
}
else
{
SpatialAwarenessSystem.ResumeObservers();
_isObserverRunning = true;
}
Question: How do I start and stop spatial mapping the right way, so that I can save some performance and still have the colliders of the spatial map to interact with.
My specs:
MRTK v2.0.0
Unity 2019.2.0f1
Visual Studio 2017
!--Edit--inlcuding-Solution--!
1. With option #1 I was wrong. It does what its meant for, but I used it the wrong way. If you disable for example SpatialAwarenessSystem while running the spatial mapping process, it disables the whole process including the created spatial map. So after that you cant interact with the invironment.
2. What worked for me was using for the start ResumeObservers() in combination with setting display option to visible and for stopping spatial mapping the method SuspendObservers() in combination with display option none.
3. The Nullreference if fixed by rewritting and casting to IMixedRealityDataProviderAccess:
if (CoreServices.SpatialAwarenessSystem is IMixedRealityDataProviderAccess provider)
{
foreach (var observer in provider.GetDataProviders())
{
if (observer is IMixedRealitySpatialAwarenessMeshObserver meshObs)
{
meshObs.DisplayOption = option;
}
}
}
4. Performance: To get your fps back after starting an observer, you really need to disable the system via MixedRealityToolkit.SpatialAwarenessSystem.Disable();, but this will of course disable also the spatial map, so you cant interactive with it anymore.
#Perazim,
The recommendation is based on your option #3. Call ResumeObservers() to start and SuspendObservers() to stop. There is no need to call ClearObservations() unless you wish to have them removed from your scene.
The example calls ClearObservations() to illustrate what was, at the time, a new feature added to the Spatial Awareness system.
Please file an issue on GitHub (https://github.com/microsoft/MixedRealityToolkit-Unity/issues) for #1 (failure of Enable() and Disable() to impact the system). Those methods should behave as advertised.
Thank you!
David

Unity5.6 Collision2D contact points array index out of range error

When I updated my Unity version 5.5 to 5.6, an error occured about the Collision2D.contacts array. When I try to access the contacts array, I can not get contact point info now.
void OnCollisionExit2D(Collision2D col)
{
if (col.gameObject.CompareTag("Ground"))
{
if ((_transform.position.y - col.contacts[0].point.y) > colliderHeight / 2 + .15f)
{
Debug.Log ("Contact count = " + col.contacts.Length);
_onGround = false;
ParticleController.PlayDustEffect ();
}
}
}
Error Log :
IndexOutOfRangeException: Array index is out of range.
Player.OnCollisionExit2D (UnityEngine.Collision2D col) (at Assets/Scripts/CharacterController/Player.cs:759)
How can I fix the error?
Thanks for your time.
It seems the exit point of collision is not computed anymore in Unity 5.6. Some changes about collisions detection have been changed in this version:
Physics: The internal 2D contact processing has been completely re-written, providing a more robust and reliable reporting of contacts.
I guess the logic for it is the following: why would there be a contact point if the two colliders are not touching each other anymore? As there is no contact point anymore, col.contacts is empty there. So when you are trying to access col.contacts[0], the element doesn't exist, triggering the IndexOutOfRangeException.
From the Collision.contacts documentation (not the Collision2D.contacts one, but I suppose the behavior is the same):
Every contact contains a contact point, normal and the two colliders that collided (see ContactPoint). From inside OnCollisionStay or OnCollisionEnter you can always be sure that contacts has at least one element.
So OnCollisionExit does not, in any case, guarantee the presence of at least one point in col.contacts.
For those searching for ArrayIndexOutOfRange errors while trying to access the ContactPoint2D on a Collision2D, it seems that the API is now:
collision.getContacts(myContacts)
where you initialize and pass in an empty array myContacts. See more about this in the documentation about Collision2D.contacts which says:
The specific points of contact with the incoming Collider2D. You
should avoid using this as it produces memory garbage. Use
GetContacts instead.

How to use the new BufferWithTimeOrCount in Rx that returns IObservable<IObservable<T>> instead of IObservable<IList<T>>

On Windows Phone 7 there is a new version of the BufferWithTimeOrCount extension method for IObservable that returns a "stream of streams" instead of the previous "stream of lists". I'm having difficulty trying to use either the new or old methods, so maybe I just don't understand how it works, but my goal is to create a stream that only fires when an existing stream matches a specified time based pattern during the previous 2 touch events. So far I have created streams for TouchUp and TouchDown (see related question) and In pseudo code I want something like:
//BufferLast2 should contain the last 1 or 2 touch events that occurred in the last 500ms. If no touches occurred this should return an empty set
var BufferLast2 = TouchDown.Merge(TouchUp).BufferWithTimeOrCount(TimeSpan.FromSeconds(0.5), 2);
//Use BufferLast2 to detect tap (TouchDown then TouchUp occuring in less than 0.5s)
var TouchTap = from touch2 in BufferLast2
where touch2.Count == 2 && touch2.First().Action == TouchAction.Down && touch2.Last().Action == TouchAction.Up
select touch2.First(); //returns initial TouchDown event
//Use BufferLast2 to detect Hold (TouchDown with no TouchUp occuring in 0.5s)
var TouchHold = from touch2 in BufferLast2
where touch2.Count == 1 && touch2.First().Action == TouchAction.Down
select touch2.First(); //returns initial TouchDown event
When using the "Stable" Microsoft.Phone.Reactive version of Rx that is built into the ROM calling IObservable<Class>.BufferWithTimeOrCount(...) returns a IObservable<IList<Class>>, which is pretty easy to work with using the standard list operators (as outlined above), but for some reason BufferLast2 was always returning two down events instead of the Down->Up sequence that I expected.
I figured it might be a bug in the code, so I tried adding a reference to the latest version of Rx and used the Observable Extensions from C:\Program Files (x86)\Microsoft Cloud Programmability\Reactive Extensions\v1.0.2838.0\WP7\System.Reactive.dll in which BufferWithTimeOrCount(...) returns a IObservable<IObservable<Class>>. This makes simple filters like Where x.Count == 2 or Where x.First().P == ... much harder to write. I haven't actually figured out how to do a simple filter like x.Count() == 2 on this return value without creating a completely separate subscription or Subject object, which seams way too complex. It's probably a simple error like my last question (all I needed was a Where clause :-P) but it is really driving me bonkers. Any help?
Changing the api makes the buffering look more Rx-y and fits with their Window operator implementation (wouldn't be surprised if using reflector you'd be able to see the Buffer operators using Window). I would think there's probably a variety of reasons that they've changed it. I'm not going to second guess them as they're a lot smarter than me!
So here's my stab at a solution. There may be a cleaner way to get what you're after but i'd probably implement my own extention method to buffer into a list. Maybe something like:
public static class BufferToList
{
public static IObservable<IEnumerable<TSource>> BufferToList<TSource>(this IObservable<TSource> source)
{
return Observable.CreateWithDisposable<IEnumerable<TSource>>(observer =>
{
var list = new List<TSource>();
return source.Subscribe(list.Add,
observer.OnError,
() =>
{
observer.OnNext(list);
observer.OnCompleted();
});
});
}
}
Then something like:
TouchDown.Merge(TouchUp)
.BufferWithTimeOrCount(TimeSpan.FromSeconds(0.5), 2)
.Select(bufferedValues => bufferedValues.BufferToList())
.Subscribe(OnBufferOpen)
private void OnBufferOpen(IObservable<IEnumerable<IEvent<IEventArgs>>> bufferedListAsync)
{
bufferedListAsync.Where(list => list.Count() == 2);
}
I suggest if you want a full explanation of why they've changed the api, go and ask the question over on the rx forums on msdn
The latest release of Rx, v1.0.2856.0, provides both buffers and windows. For the buffers, we restored the original signatures, based on IList. The corresponding window operators will return nested observable sequences.
The way the Buffer* operators are implemented is by composing the corresponding Window* operator with the new ToList extension method that takes an IObservable into an IObservable>. All the Buffer* operator does is invoke this new ToList operator in a SelectMany selector.

Quickly Testing Database Connectivity within the Entity Framework

[I am new to ADO.NET and the Entity Framework, so forgive me if this questions seems odd.]
In my WPF application a user can switch between different databases at run time. When they do this I want to be able to do a quick check that the database is still available. What I have easily available is the ObjectContext. The test I am preforming is getting the count on the total records of a very small table and if it returns results then it passed, if I get an exception then it fails. I don't like this test, it seemed the easiest to do with the ObjectContext.
I have tried setting the connection timeout it in the connection string and on the ObjectConntext and either seem to change anything for the first scenario, while the second one is already fast so it isn't noticeable if it changes anything.
Scenario One
If the connect was down when before first access it takes about 30 seconds before it gives me the exception that the underlying provider failed.
Scenario Two
If the database was up when I started the application and I access it, and then the connect drops while using the test is quick and returns almost instantly.
I want the first scenario described to be as quick as the second one.
Please let me know how best to resolve this, and if there is a better way to test the connectivity to a DB quickly please advise.
There really is no easy or quick way to resolve this. The ConnectionTimeout value is getting ignored with the Entity Framework. The solution I used is creating a method that checks if a context is valid by passing in the location you which to validate and then it getting the count from a known very small table. If this throws an exception the context is not valid otherwise it is. Here is some sample code showing this.
public bool IsContextValid(SomeDbLocation location)
{
bool isValid = false;
try
{
context = GetContext(location);
context.SomeSmallTable.Count();
isValid = true;
}
catch
{
isValid = false;
}
return isValid;
}
You may need to use context.Database.Connection.Open()