/*
* Copyright 2008-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package griffon.pivot.test;
import griffon.core.GriffonApplication;
import griffon.exceptions.GriffonException;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Window;
import org.codehaus.griffon.runtime.pivot.TestDesktopPivotApplication;
import javax.annotation.Nonnull;
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CountDownLatch;
import static griffon.pivot.support.PivotUtils.findComponentByName;
import static griffon.util.GriffonNameUtils.requireNonBlank;
import static java.util.Objects.requireNonNull;
/**
* @author Andres Almiray
* @since 2.0.0
*/
public class GriffonPivotFuncRule extends GriffonPivotRule {
private static final String ERROR_RUNNABLE_NULL = "Argument 'runnable' must not be null";
private Window window;
public GriffonPivotFuncRule() {
}
public GriffonPivotFuncRule(@Nonnull String[] startupArgs) {
super(startupArgs);
}
@Override
@SuppressWarnings("ConstantConditions")
protected void before(@Nonnull GriffonApplication application, @Nonnull Object target) throws Throwable {
application.startup();
application.ready();
TestDesktopPivotApplication.getReadyLatch().await();
window = (Window) application.getWindowManager().getStartingWindow();
}
@Nonnull
public Window getWindow() {
return window;
}
@Nonnull
public <T> T find(@Nonnull String name, Class<T> type) {
requireNonBlank(name, "Argument 'name' must not be blank");
requireNonNull(type, "Argument 'type' must not be null");
Component component = findComponentByName(name, window);
if (component != null) {
if (type.isAssignableFrom(component.getClass())) {
return type.cast(component);
}
throw new IllegalArgumentException("Could not find a component name '"
+ name + "' with type " + type.getName()
+ "; found type " + component.getClass().getName() + " instead");
}
throw new IllegalArgumentException("Could not find a component name '" + name + "' with type " + type.getName());
}
public void runInsideUISync(@Nonnull final Runnable runnable) {
requireNonNull(runnable, ERROR_RUNNABLE_NULL);
Throwable t = null;
final CountDownLatch latch = new CountDownLatch(1);
final Runnable worker = new Runnable() {
@Override
public void run() {
try {
runnable.run();
} finally {
latch.countDown();
}
}
};
try {
EventQueue.invokeAndWait(worker);
} catch (InterruptedException e) {
latch.countDown();
t = e;
} catch (InvocationTargetException e) {
latch.countDown();
t = e.getTargetException();
}
try {
latch.await();
} catch (InterruptedException e) {
throw new GriffonException(e);
}
if (t != null) {
if (t instanceof AssertionError) {
throw (AssertionError) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new GriffonException(t);
}
}
}
public void runInsideUIAsync(@Nonnull final Runnable runnable) {
requireNonNull(runnable, ERROR_RUNNABLE_NULL);
final Throwable[] ts = new Throwable[1];
final CountDownLatch latch = new CountDownLatch(1);
final Runnable worker = new Runnable() {
@Override
public void run() {
try {
runnable.run();
} catch (Throwable t) {
ts[0] = t;
} finally {
latch.countDown();
}
}
};
EventQueue.invokeLater(worker);
try {
latch.await();
} catch (InterruptedException e) {
throw new GriffonException(e);
}
if (ts[0] != null) {
if (ts[0] instanceof AssertionError) {
throw (AssertionError) ts[0];
} else if (ts[0] instanceof RuntimeException) {
throw (RuntimeException) ts[0];
} else {
throw new GriffonException(ts[0]);
}
}
}
}