From d92f85e1b8cef50aef54aca6dbdab8c92decd448 Mon Sep 17 00:00:00 2001 From: Edward Jakubowski Date: Thu, 3 Apr 2014 22:29:36 -0400 Subject: [PATCH] Adding WpfBridge for automation of WPF and Silverlight WpfBridge allows java to access .net 4 UI Automation libraries. This library enables Synthuse to access and automation WPF and Silverlight apps. --- .classpath | 1 + .gitignore | 3 + build.xml | 5 +- native/WpfBridge/AssemblyInfo.cpp | 46 ++++ native/WpfBridge/Global.cpp | 10 + native/WpfBridge/Global.h | 20 ++ native/WpfBridge/ReadMe.txt | 9 + native/WpfBridge/Stdafx.cpp | 5 + native/WpfBridge/Stdafx.h | 7 + native/WpfBridge/WpfAutomation.cpp | 187 ++++++++++++++++ native/WpfBridge/WpfAutomation.h | 39 ++++ native/WpfBridge/WpfBridge.vcxproj | 181 +++++++++++++++ native/WpfBridge/WpfBridge.vcxproj.filters | 62 ++++++ native/WpfBridge/WpfBridge.vcxproj.user | 3 + native/WpfBridge/app.ico | Bin 0 -> 1078 bytes native/WpfBridge/app.rc | Bin 0 -> 2558 bytes native/WpfBridge/bin/wpfbridge32.dll | Bin 0 -> 74240 bytes native/WpfBridge/bin/wpfbridge64.dll | Bin 0 -> 88576 bytes native/WpfBridge/build.bat | 5 + native/WpfBridge/org_synthuse_WpfBridge.cpp | 230 ++++++++++++++++++++ native/WpfBridge/org_synthuse_WpfBridge.h | 115 ++++++++++ native/WpfBridge/resource.h | 3 + src/org/synthuse/Api.java | 2 +- src/org/synthuse/CommandPopupMenu.java | 2 +- src/org/synthuse/WpfBridge.java | 90 ++++++++ synthuse.properties | 2 +- 26 files changed, 1023 insertions(+), 4 deletions(-) create mode 100644 native/WpfBridge/AssemblyInfo.cpp create mode 100644 native/WpfBridge/Global.cpp create mode 100644 native/WpfBridge/Global.h create mode 100644 native/WpfBridge/ReadMe.txt create mode 100644 native/WpfBridge/Stdafx.cpp create mode 100644 native/WpfBridge/Stdafx.h create mode 100644 native/WpfBridge/WpfAutomation.cpp create mode 100644 native/WpfBridge/WpfAutomation.h create mode 100644 native/WpfBridge/WpfBridge.vcxproj create mode 100644 native/WpfBridge/WpfBridge.vcxproj.filters create mode 100644 native/WpfBridge/WpfBridge.vcxproj.user create mode 100644 native/WpfBridge/app.ico create mode 100644 native/WpfBridge/app.rc create mode 100644 native/WpfBridge/bin/wpfbridge32.dll create mode 100644 native/WpfBridge/bin/wpfbridge64.dll create mode 100644 native/WpfBridge/build.bat create mode 100644 native/WpfBridge/org_synthuse_WpfBridge.cpp create mode 100644 native/WpfBridge/org_synthuse_WpfBridge.h create mode 100644 native/WpfBridge/resource.h create mode 100644 src/org/synthuse/WpfBridge.java diff --git a/.classpath b/.classpath index 2762e90..3c497e1 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,7 @@ + diff --git a/.gitignore b/.gitignore index 0f84274..dc6b6da 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ build/ lib/ dist/ synthuse.properties +native/WpfBridge/x64 +native/WpfBridge/release +!native/WpfBridge/bin \ No newline at end of file diff --git a/build.xml b/build.xml index 732ae6c..a4edace 100644 --- a/build.xml +++ b/build.xml @@ -39,7 +39,7 @@ - + @@ -58,6 +58,9 @@ + + + diff --git a/native/WpfBridge/AssemblyInfo.cpp b/native/WpfBridge/AssemblyInfo.cpp new file mode 100644 index 0000000..118f215 --- /dev/null +++ b/native/WpfBridge/AssemblyInfo.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ +#include "stdafx.h" + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly:AssemblyTitleAttribute("WpfBridge")]; +[assembly:AssemblyDescriptionAttribute("")]; +[assembly:AssemblyConfigurationAttribute("")]; +[assembly:AssemblyCompanyAttribute("Synthuse")]; +[assembly:AssemblyProductAttribute("WpfBridge")]; +[assembly:AssemblyCopyrightAttribute("Copyright (c) Synthuse 2014")]; +[assembly:AssemblyTrademarkAttribute("")]; +[assembly:AssemblyCultureAttribute("")]; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the value or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly:AssemblyVersionAttribute("1.0.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; + +[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; diff --git a/native/WpfBridge/Global.cpp b/native/WpfBridge/Global.cpp new file mode 100644 index 0000000..6832972 --- /dev/null +++ b/native/WpfBridge/Global.cpp @@ -0,0 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ +#include "StdAfx.h" +#include "Global.h" +#include "WpfAutomation.h" + diff --git a/native/WpfBridge/Global.h b/native/WpfBridge/Global.h new file mode 100644 index 0000000..d7b5a56 --- /dev/null +++ b/native/WpfBridge/Global.h @@ -0,0 +1,20 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ +#pragma once +#include "WpfAutomation.h" +namespace Globals +{ + using namespace System; + + public ref class Global + { + public: + static WpfAutomation ^WPF_AUTO = gcnew WpfAutomation(); + }; + +} + diff --git a/native/WpfBridge/ReadMe.txt b/native/WpfBridge/ReadMe.txt new file mode 100644 index 0000000..4d5f4e6 --- /dev/null +++ b/native/WpfBridge/ReadMe.txt @@ -0,0 +1,9 @@ +======================================================================== + DYNAMIC LINK LIBRARY : WpfBridge Project Overview +======================================================================== + +Created By Edward Jakubowski ejakubowski7@gmail.com + +Description: +This is a bridge for java to access .net 4 UI Automation libraries. This +library enables Synthuse to access and automation WPF and Silverlight apps. diff --git a/native/WpfBridge/Stdafx.cpp b/native/WpfBridge/Stdafx.cpp new file mode 100644 index 0000000..a9a851a --- /dev/null +++ b/native/WpfBridge/Stdafx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// WpfBridge.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/native/WpfBridge/Stdafx.h b/native/WpfBridge/Stdafx.h new file mode 100644 index 0000000..3cc4c24 --- /dev/null +++ b/native/WpfBridge/Stdafx.h @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + + diff --git a/native/WpfBridge/WpfAutomation.cpp b/native/WpfBridge/WpfAutomation.cpp new file mode 100644 index 0000000..fa4cd59 --- /dev/null +++ b/native/WpfBridge/WpfAutomation.cpp @@ -0,0 +1,187 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ +#include "StdAfx.h" +#include "WpfAutomation.h" + +using namespace System; +using namespace System::Windows::Automation; + +WpfAutomation::WpfAutomation(void) +{ + this->frameworkId = WpfAutomation::DEFAULT_FRAMEWORK; +} + +void WpfAutomation::setFrameworkId(System::String ^propertyValue) +{ + this->frameworkId = propertyValue; +} + +array ^ WpfAutomation::convertRuntimeIdString(System::String ^runtimeIdValue) +{ + System::String ^delim = L"-"; + array ^idStrArray = runtimeIdValue->Split(delim->ToCharArray()); + array ^idArray = gcnew array(idStrArray->Length); + for(System::Int32 i = 0 ; i < idStrArray->Length ; i++) + { + idArray[i] = System::Int32::Parse(idStrArray[i]); + } + return idArray; +} + +AutomationElement ^ WpfAutomation::findAutomationElementById(System::String ^runtimeIdValue) +{ + array ^idArray = this->convertRuntimeIdString(runtimeIdValue); + Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId); + Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray); + Condition ^frameworkAndRuntimeId = gcnew AndCondition(pcFramework, pcRunId); + return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndRuntimeId); +} + +array ^ WpfAutomation::getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection) +{ + array ^idStrArray = gcnew array(collection->Count); + System::Int32 count = 0; + for each(AutomationElement ^child in collection) + { + System::Object ^currentVal = child->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty); + if (currentVal != nullptr) + { + array ^idArray = (array ^)currentVal; + for each(System::Int32 val in idArray) + { + idStrArray[count] += System::Convert::ToString(val) + L"-"; + //System::String->Concat(idStrArray[count], System::String->Concat(val->ToString(), L"-")); + } + idStrArray[count] = idStrArray[count]->TrimEnd('-'); + //System::Console::WriteLine("id: {0}", idStrArray[count]); + } + ++count; + } + return idStrArray; +} + +//Descendants will walk the full tree of windows, NOT just one level of children +System::Int32 WpfAutomation::countDescendantWindows() +{ + //AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition); + AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + System::Int32 result = aec->Count; + //delete aec; + return result; +} + +System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + System::Int32 result = aec->Count; + //delete aec; + //delete frameworkAndRuntimeId; + return result; +} + +System::Int32 WpfAutomation::countChildrenWindows() +{ + //AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition); + AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + System::Int32 result = aec->Count; + //delete aec; + return result; +} + +System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + System::Int32 result = aec->Count; + //delete aec; + //delete frameworkAndRuntimeId; + return result; +} + +array ^ WpfAutomation::enumChildrenWindowIds(System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + return getRuntimeIdsFromCollection(aec); +} + +array ^ WpfAutomation::enumDescendantWindowIds(System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + return getRuntimeIdsFromCollection(aec); +} + +array ^ WpfAutomation::enumDescendantWindowIds(System::Int32 processId) +{ + Condition ^frameworkAndProcessId = gcnew AndCondition( + gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId), + gcnew PropertyCondition(AutomationElement::ProcessIdProperty, processId)); + AutomationElement ^parent = AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndProcessId); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + return getRuntimeIdsFromCollection(aec); +} + +array ^ WpfAutomation::EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle) +{ + //AutomationElement test = AutomationElement.FromHandle(new System.IntPtr(123123)); + AutomationElement ^parent = AutomationElement::FromHandle(windowHandle); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + return getRuntimeIdsFromCollection(aec); +} + +System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + //System::Object ^currentVal = parent->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty); + array ^aps = parent->GetSupportedProperties(); + for each(AutomationProperty ^ap in aps) + { + //System::Console::WriteLine("property: {0}", ap->ProgrammaticName); + if (ap->ProgrammaticName->Contains(L"." + propertyName) || ap->ProgrammaticName->Equals(propertyName)) + { + System::Object ^currentVal = parent->GetCurrentPropertyValue(ap); + return currentVal->ToString(); + } + } + return nullptr; +} + +array ^ WpfAutomation::getProperties(System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + array ^aps = parent->GetSupportedProperties(); + array ^propStrArray = gcnew array(aps->Length); + System::Int32 count = 0; + for each(AutomationProperty ^ap in aps) + { + System::Object ^currentVal = parent->GetCurrentPropertyValue(ap); + if (currentVal == nullptr) + continue; + propStrArray[count] = ap->ProgrammaticName; + ++count; + } + return propStrArray; +} + +array ^ WpfAutomation::getPropertiesAndValues(System::String ^runtimeIdValue) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + array ^aps = parent->GetSupportedProperties(); + array ^propStrArray = gcnew array(aps->Length); + System::Int32 count = 0; + for each(AutomationProperty ^ap in aps) + { + System::Object ^currentVal = parent->GetCurrentPropertyValue(ap); + if (currentVal == nullptr) + continue; + propStrArray[count] = ap->ProgrammaticName + ":" + currentVal->ToString(); + ++count; + } + return propStrArray; +} diff --git a/native/WpfBridge/WpfAutomation.h b/native/WpfBridge/WpfAutomation.h new file mode 100644 index 0000000..e1ce513 --- /dev/null +++ b/native/WpfBridge/WpfAutomation.h @@ -0,0 +1,39 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ +#pragma once + +public ref class WpfAutomation +{ +public: + WpfAutomation(void); + void setFrameworkId(System::String ^propertyValue); //default is WPF, but also accepts Silverlight, Win32 + + //Descendants will walk the full tree of windows, NOT just one level of children + System::Int32 countDescendantWindows(); + System::Int32 countDescendantWindows(System::String ^runtimeIdValue); + + System::Int32 countChildrenWindows(); + System::Int32 countChildrenWindows(System::String ^runtimeIdValue); + + array ^ enumChildrenWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop + array ^ enumDescendantWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop + array ^ enumDescendantWindowIds(System::Int32 processId); + array ^ EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle); + //In all the above Enumerate methods will return a list of Runtime Ids for all related windows. + + System::String ^getProperty(System::String ^propertyName, System::String ^runtimeIdValue); + array ^ getProperties(System::String ^runtimeIdValue); + array ^ getPropertiesAndValues(System::String ^runtimeIdValue); +private: + array ^ convertRuntimeIdString(System::String ^runtimeIdValue); + System::Windows::Automation::AutomationElement ^ findAutomationElementById(System::String ^runtimeIdValue); + array ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection); + + static System::String ^DEFAULT_FRAMEWORK = L"WPF"; + System::String ^frameworkId; +}; + diff --git a/native/WpfBridge/WpfBridge.vcxproj b/native/WpfBridge/WpfBridge.vcxproj new file mode 100644 index 0000000..93b88ec --- /dev/null +++ b/native/WpfBridge/WpfBridge.vcxproj @@ -0,0 +1,181 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3141812E-36D5-4E7C-A388-EFED9AE250A5} + v4.0 + ManagedCProj + WpfBridge + + + + DynamicLibrary + true + true + Unicode + + + DynamicLibrary + true + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) + + + true + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) + + + false + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) + + + false + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + Use + + + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + Use + + + true + + + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + Use + + + true + + + + + mkdir "$(ProjectDir)bin" +copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)" + + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + Use + + + true + + + + + mkdir "$(ProjectDir)bin" +copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)" + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + \ No newline at end of file diff --git a/native/WpfBridge/WpfBridge.vcxproj.filters b/native/WpfBridge/WpfBridge.vcxproj.filters new file mode 100644 index 0000000..9689af0 --- /dev/null +++ b/native/WpfBridge/WpfBridge.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/native/WpfBridge/WpfBridge.vcxproj.user b/native/WpfBridge/WpfBridge.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/native/WpfBridge/WpfBridge.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/native/WpfBridge/app.ico b/native/WpfBridge/app.ico new file mode 100644 index 0000000000000000000000000000000000000000..3a5525fd794f7a7c5c8e6187f470ea3af38cd2b6 GIT binary patch literal 1078 zcmeHHJr05}7=1t!Hp3A*8IHkVf+j?-!eHY14Gtcw1Eb*_9>Bq^zETJ@GKj{_2j4$w zo9}xCh!8{T3=X##Skq>ikMjsvB|y%crWBM2iW(4pI}c%z6%lW!=~4v77#3{z!dmB1 z__&l)-{KUYR+|8|;wB^R|9ET$J@(@=#rd^=)qs85?vAy(PSF5CyNkus435LVkZ$rj zNw|JG-P7^hF<(;#o*Vk}5R#e|^13tBbQkeF?djULtvqyxd3<{9 literal 0 HcmV?d00001 diff --git a/native/WpfBridge/app.rc b/native/WpfBridge/app.rc new file mode 100644 index 0000000000000000000000000000000000000000..eab43064f13cd0a8912887c2c7299ddb6d7d2240 GIT binary patch literal 2558 zcmds(T~8B16o%hx6aT}cz0qh|kt;8OHl(p2u|ObcVzjun$-0o1ioYIx-q}uzY&RON zHfA$lXU?2CAMZJ{zwW#0D(FZvO*GfF7PL&a(9WSPwA5$itPb>wFX)@Ts-VrG-!fi7 zn=|^{lG%iLU}b4D-N4h)b3NmhZXDZC3wCq3uOe@&a=xRfT9Ml)+mSDe=PY|qCmQKg zXXO<`@Kh{u}P)77e+J`b^ZYfCz>(RWgv~!7P?33(2w$i>2#H#>Fc|_Qh z^$Vg|uu6y;F)Q)4&`b6oBW$sbY4hW1i<6cC#7@YRVoj;;1hOW_dS{Ze%gCRTQO?P0 zWC0DOPI5U zsW~oLw6^XIsan`<>ynio16ff0_sBq)>sz3jP1&!{CS&XIJM!nhN%CW}eNvC;0#Epr I_*Z2A2KzE2Bme*a literal 0 HcmV?d00001 diff --git a/native/WpfBridge/bin/wpfbridge32.dll b/native/WpfBridge/bin/wpfbridge32.dll new file mode 100644 index 0000000000000000000000000000000000000000..7fd09497656c17908fa69ad81931ad34e550931f GIT binary patch literal 74240 zcmeFa3wT^r)jq!Gc4jh@d(xygXv!q*v`uWHN2i=052q+|qQCHYsURa)EMd zQwFrP6bhoEq80`b6+iG31r;?gAfTwoCx}{Wbr8!R-?k{LssKPH$(J~r@Zd~~8bE{JaGJ$*3DbKFx=IyI7S)Y%-bA_6Q#C1Qa?6Bk z1^c^_EYh2ms!780hq`tS0hcXpJ<{cwz(dKiX7T&3Ot1m+-x5>qA2g6DkBlX(Wt}^4cHtU)h zlQ*uJgUmT|pMH9*1id2rY523NoFto~+i`(mhORGWiJ!3&yS8_z+=RW|x~AwZGlL^F z!&r&yJ?!r>?a{ZB3m7X&*Y<|W8~5)(0r#63FgTMkjFn`+m;FPgJ!Fb~zP7ijEcizq za;$En)a9FlHZ(T6jpW)&`%F&QrzPU?U5(bYise|z^n_l9jQrS2?N-~GRyrChDbjkG zcg!DV)GazzQmpkZRRJ~Tk_qvoPbrc?=Cb;Hh_C=ZzAI6>$61zVQl*{&M7CpaHq=)- z3pb`zV64QK@V`O(x2M!M-BvUsKYEvybeZE9mYx)Cj7}%Kkjd7 zxr2c(oj0Yx?y%Z?rZd};Y=a@D8I#XPkimHcNv@OX7>{>}_J8v66dz-SBMo{iS;zbR zpcjpGO(PWXA;@vL6mde6W4%gLzB6Ft$+h@q;#@idi6SJ1XDDUCbuf&6q}*Cv_FIWc z#&&#c*-CNYKZRzRXIOow!4d|dPe&Q@W4#KKzuk8gEauu4S``XY=mA5(Q{F{0Wv8G7Foh|=sN+E)k$WsJ{9yJULteMpK< znje-W+A}^EnRa_=H&(Jz>#YiLBwtU%R=C+c&pHX=`gX#&RmRC!Nkzh6e0*8gnDv!H z$4aUbddv)FUDhPWQJFx}riMstSj!EoY(Q2)_k~oVVeK^NG&E>$OR@hjn~SD(wF> z;;{NKxXu1;RR~m-OI_EbyUMKjb6p;%+qtULg}K3PtSUQhINLH@X+A7jNu7`WJ9T^6 z*j{HQ#)7rr8W}3~d>`gmcd5fx&^oW)E=#B3$+bFl>siNJ57)!)LmiA<>l$}1E-8kQ zc(56*(lQv~(3mY)!1hxU>7@3Whx%ZJQLRbsBJI?J!;0gQB>ug|w+CYnlL&uor5Q;> ze_pn-`aXw%jyTO(;xLLSdIe++IBR@$4|CIBA z2Y${mvtZqubMkCwB+;Bk81LubE8a5rlh|Y)l`(UYc<+wKi>n~|9BY|9-!pHj)oo4g zB-XZctBak)<22`lv6AjY|C6z|0(o;S)~3PFz@yt{_$Hxq%yP0VFn4ln%B7#Wv7i-W zv|!>89V_Wg_>=xFKh{FFXG(ug(n;(|ItRD!E2R$hg4BH!mPUJi`n;)z$3U&Hw0oTB z`c9)Q!!WykI;U2b?>cd5H;{Ycu4=4ghmOzqHLMP$ci_bfEjo476&Xyg1m`^lQwk)LPGJI%@&jd^ZsjyuOA7x8|KJM5mZV&vpG20w``d1*OmdG-QN zf$PQv0hjYrc^SDGId*f0AaUlotT`^^OxkznIjuPkXO0tW(q5L`z;)x|Z=Z0%kGOK| z+)W(T=N!jenFC~=xe7-J#}OPdwq#7nH5)6rn(g=RZKM7FYuae6WF*l(ccR^@qz{?H z&fequ25UWHAc`Y4Y0TpAy%=JmfWQNJ(2#?SiY zrrCW3m#v?H+I58_Y6SIOLMh;9J=`wY=3OA;^Fm<>vb$E;%k2!TX%w}|8@;D$P-JLWc zo56NSf_W9Q?9fOZ0=iNaJoq{TxT?_`e}>{r`P)GREw?&V!lt zDk*;OTqHAgVVmmCF+uv|1B>C-Z4{*4X%xEdGzPK%a(jGdLr!)25R}}9cosU;*Wnkp zxjDA}&{3a}phAVpVW8b}d9}*=|6aS=i-tw@NqL*2Qjh^1?j0|1<-X zI>~*t)XC;s0EZ{fkrW>L|M|#+drRCy@VaEA`Q{_9j2rAXt6avXJWgLJm;ooona%8K zxX*HzO)+^}KkiW7Wgd@I&aFC)##PTY?^@1C2_wzF{!SvTI^dDzOBC1LxEj>-YT zZLYf@$FZOU1!v^oW<^FrX=aYynZ_vYluc~Bs9)vqdA6PR!gwGdV_2@GjGlyVlwtAC_?mP}*7aXQs&jvagt))WZkp~3q&Lz0)tnX4p~CKCD0OVo z5;)nWf*Z!3zkYQ153f3(2&5ygx?>^yZnIu|{pe8Iwi(CfIFx#IdG`Y_?!Fh|35V## z@R$p#wzlg>v#!4q(@FO|VsaP6v6oT9wtY**u>4nT%P&eFcA=O_70@j|tpe=O^lmvF zvx^}L$`~8YUOzVMf(_^~R{dq!c%3rbcM{=-k6VW_5bV|B@8$cEacrqvhW$%dqRg@9 z(EteZx-b=TX~v%4|HA%2`o2K+zKdMpSM4h|w|9fNSW%ef8P<>fzM2|Akk-G&Y<*Ht8UIwV58+ zCD=L2MRZlr{V17>=nbVef2NC{Ghbfn?sK9yVl|Pcih{ovR6DZ1WnCxRc`(Or`q$VPNNJK0O*No2v3u7tT#W8ew4o_@>}+rw&_j;3!=5g2sSIJp zp1J;SQj~4jFaFMh9+_-2&4Px^@?l&OFaOnP`vb4-ckNHxSAVpr`PeV9xU{uJ_jer& zcfF{jPd^cO2M;C3j-?@<{ec&cEkN1PCmd2)&|~KKkRCqlI93N8I?Mk0?EUM~k3Efi zZ5N^8y5GbQIrc*++oId@yPKpDBPeKMS9mdeT&|7uwpO`3uXb*89lKkyNg(lSjK(l8 zvvh)^2LeZ%4g_9ol46(2C?9*i=~yrFgdfB8K0G%3;@I=NwqwIbk&^C_TBF0qEu0_1pyw_`1+-QQoBHv0D$+G;M6N#&u*2>iPuHtavX;`@VH`<-Y>>)12lC+sWU z9r#nbOcv`ODiSLZ?`eg*beWmPN~9Bxl}NXa-@~!={q?Sg>ahZBS#BA!mye?G%9XZ9 z_AHZ^=)-T6Kl@D&#@CkRHIuV$eRTh$7e(WlaW?a#pVzFkJ(=}jWqxpd)`OQC<O6P@nF! z`6|2f4)g=n6n@PWT)*LtL+AyI0>{fA$2EAfGa{;eUB}SClIq5heQYk8G5nYvE!Da| z;F4#7*-fUVi5eF)XYa2le&pDUzdsW`YSC9`fBl=C`!d8$8-m*Zdo+Ud)ADEcEXU+F z%9=|z)#l}+CuYF2E4J?r%3jKDNVXAsY;O1*8INi>jhzlp)Uq+6rOU>f)U5Lu);sk6 z>f-Euy~WuFaLhY8Uj27aebjnv`1t<7J31arL5UWLCWmHLra9it@-e@feZKp5Xx(mU z&|^=bu<&D(rPE>U3BQ)jb`EzP=YR}u_+GSp-G{MxOEb0zXM(jXO zIF4gdO0%ocCmin}#T82;-*^2B$a05Nbl>%dksO=kLIol<$h6IJ47UxcZ5tNpbdcST zq4$hU%0@DLju@z67i?s6-qtO?$0p@NhlZYv(^Jv0l3Q_>d#7xe$j`fZyVl^AW>UGW zV4kJ$*|}pS_oHC*{wm!xiQ5#uYZ3he@1-v=^$#WVNo7>0mho`H2KQJBGfmEfILfSr zb3r9%D>W&JRw5~jXOUvd?1gyKSKu}zz)?6i_eT3G>@qi{-YfdH%l=dD@nl7jAFIvo z>lKo=sr)4gKI#32?f=$C(mUa+CR@z!E|UFTLsDY<1mfzDy=(sfx4P!JzaJodp0Vo! zIa_^S!?w0G(>zn>(K^r6189A@A+`2j3fnua{e$AiZJzOj$w?o14x=!~ai^=);mWhe zIlD1A$9|`?)b7mC?lO!iX?G4_ZQfz{w!x3wBis2-E#7`Rz}g0~>}rP@%`><=w)i%J z^#8H8&iGN%lwN?D5PxNo4e`|j;Jh=_t)tBZQ<}G~{a@*|v==AP+FCNLmI|ANo zdz__)(|qcBB-1r96uu|LHbKq6f!CURN0x_k1-uC_G2;1%LRAtmO23bf;ayWvZ>tY` zK?Cjgv~Ir)eh!9K&&gHRHFzmiYn_hc^o^^nGtxx3MR-J{i^vd>DI#m*Y9H=j@p;Qw z$usaK?a_v^F^|PdcgFO3g%+F?f;O>%b;mCFHD+;$f zy+MyyGoxr@I&O2dGO^LLd2m1SU&LNBqWEI@DS{08#N&#qEfpwZsabxVv%tmXCsd6Xcd z=s2{pRsosWl&mtMc}M$0iTsfn)hHN|aCRXydug6;k1+4%jYup7BSIF8NPu#!6m}Q9 zR=#+Clxvh0`S5(l?F&MbrWHuHH)hTA>^fU=#bdHdR_2wlCO^B*fWCD0ZahV>7y598 z++|aDqoM4+Vd)z0T70!|^lYiahuKJichLoXpg-_iqI@5oez|>{A>3BX#Z!^M=PCG9 zZ`>Bo6Xkmg&PyDUh7Z#%zkAw*vwRSPPxZ#_;p08*ZN5&)0P}p9OW#85?_ui;!4#I0 z=~&j`Y}m?=>=9&vu{wNQnnagrs?U5aHIr{yc^ZD?}py)yA14Pk|?oA$D8!b zeBg_Tyz;zIE=949>n0tyb)eM|_wU;cn?m*(A3By%=A1Fpw+ji~!3)dNG%;^|ywBGc zjuau3Lf!Ai2d57+o>A(t%KT;c&<~CA!RQ+ToUF4Hva3#}8wBWMHP}~{Bx3w=BF4gz zIZ|^hSH`UI8Ai8+s0ukI;HWgw9x{gI$2zdah}X4n1igz}KKQ|cYTsQf*lbZz!NWq` zR;QcUk^cvY{Q2)1b%=piQXZ*F+b)5R&0^c>rljkhJ z6MT0;o`ahQqpamfWq}WVu`=e^^E`M~i4lZ%0(tJ;7*h5$tQ9*!Up#SxuY=8D0Ck-%G^crbjUY?66Sr`Dz7~Zvux}Vv75$+BA6D9d2S!pBcs$-nCCb$ zHODBMq>Fa3EWAZPW4LD>&T*6?2j)yjOu&d=hQHN^X~vkF*ppz*;(Cl(T~*?!z?x&l z8B>|`e|0Yo8J`tgiJ?P%2YwD{L z@nf=3BZyz`FRcUZ&UhE&H9eAP)(kz~JquUI>Z_4@EcReA!2^0+Lo}-l5k8hSj!a1x zMShYZU!GSRN2I>!8PcXQcgb1WQ|6xvU0;b6Lx62Q1?PA>#CdcfCA`@VHM$N~?rE<@ z9WV_ypr~0mW3n>j%d;5Xr5M7E)FpC#XUNgd?JW}R~#JRQlNCEr22eTc_+H)obqo8`qXsFYVA_BbSs zZ>19T`2X%}hxX-QUxIsOvpX{F);Zx15*w89Gsbq_wTHho%@tiK-__gSh9%|%a2A7RKS-=bvwO}5Q3o%%MRm;#mq`|INN2_vB|+6+$d*8<7*!Wt{(H3cVp7r^hr^^yNeI%aVLBUe@^c!lwR8 zQ-ABYJ{S4BP*04@ixEw!Q??G69;J}m7?1fqbgIqfgw5@=0gT7732Ed#1YYK?VvAB( zLvsr7fmWGy(p+gkqp-pN?O5a60pPKlXE#18%}cYbDQwG0o7`FX4LG!|nRew)S##aF8Rl(BPDW0qj0V2=&CAVk=H=w(aJ!U~w$ZJV9^0Dq zBAF9hOW+n~e0gSbUWm* z8l^qhMwnGA$V)58bLk3tbOp<;^Ik`N{kocY@rvdcW>pi;Gsc~dSJj?|c{)j889x8=1x>d05AhG=H?imYJa*jhAav%i(jjjBmNu zHVVrZ%qkj@V)kI%xUmw-RLjdbA{UXpWuyYB8AT&MH9Y-k~p3~FpN1L6|Aja zh4BmYZ{anExq9Yu{B9DT{q ze85cyrM#TLeH5jeF^)_e@51gy9ACn5CyrhmSL3(=M+@@H z&j@}`cO`H!j_EiuaoBMj1^;6lqd5K>$K5zSj^hRReFsN6@=wPx3&)M%*CUVobZfr^ zT6E4%Jc5yL`wYy31}0epv!H?5*Qmfzi6c4B#B}_3zGYugg`*g^BgNQo)F5reZ+36O zE#PC{=e?17cJ9R7w@6WKu_OR(21Y8-?*>i7@G1z(YtlQ56}McvpKg{sL{rV``j}o;J!nDI+%O; z=G7ni`jr=d>ylqtdne$)nJW8FXPNCQZSjBmBX2FU@qS+7tO~BFk{6xwlaAxECG!`~ zFJD-`NETJpz87-k2K+wbE~W0lIlmQYv&w^F@h~<(htM$IbwPFE*UW3;UA?Zh8oFNK zjd{>j_4aQTWBj14vp0<0c}|)%`r9Sta)T(PW3QmF45<}39!C1Va7g=ME#ldY3nBBH zT#xHV)3lS5p^ubtEZeT}@_bIQI3xmv|euHvd0n`anm7v+H&$4)m?WX6MFo}cjs zq@_sYRLZ54O_V*9*HYd=`CZEAivCz+sLYun=gd5I`c$=WX4TB8>Ox3E?Ib@!d64q6 zl=nf-Qa_xzWX3ENgEZ8;u^3P?lM7jFSSQYuKw4hb0N(|M<^dRLmC7%NG74koze4g@`CF1`dB~mZzEXnJnoI-iV zEa8{Vs+@&dQ=UIdO1YGB4{bg^OFVp*%;RL9rF?1D8?x15-w`SQW%FrNCEnGAi6-NX zUM0Q=#x@4J+1Ptl;#H`l3c}5q(LcOl+BCgqgj(i0EF8mJoeKqZ*?B(r5$GeHw*`?$>CD z=&KrCNA%ws-9+>?jXp#4fJWaU`npCxC;Em)uM<6}(cg(4(#VRf#CG*fjk1ZprO_0k zZ);RS^sq+riN2%JIYi&psFvt^8Z{G*YIHu)BN}xPJ*v^AL{W`)6FsKUjYN-YbUV@a zH5w&)LZj!1p48}XL{Djy>6Y65K%)|(A8K?S(bF2W5dBD_E}|c6G)(jpjXq5Dj7A5E zeyY(YiJsLcLi9fx-AnW{jUFa?PNS!Zp4aFw(a$w{o#+LP{z>!;jnX|*zh7!pNc1a> zyhMjJT1fP3jm{xDqEQ{uZ!~HnI;v3@(Qh@njOce7?IDV3bb#nZjXp{AdyPI%^pZwj zBl?3z-z7Sx(GQ7U*60PIS2TK&=v9s0BzjGwe-gc}krSKe?dp#jO(J?jqhg{rHCjUS zCynZf{;bh(U?Z}5h=@;xd;0mkwv4Q5Lq?)HIYrD*NN;JIq>*!yK-nW zm&nklk;tjh5Rprx-9%{`-ALrt=sqHkM$ZtXYjl_>L!&o|GBx@qQIQ6y?6G(QdcVyjKc`?oB}tr=TCCpr5CpSPJ@M3i@XXau&v0Lh7EEKyq!*NFdS8 zNkK~!NEKz{NlSC#U)i35dNuklC1?cbX?vmNt9%A=7m&j;#quC^57Ba(<=b5Gj=<-3 zHO=xJA_FfswyWtH%_lldqxD3mYt%(FL!%psiZptVXr@L-iO$d{4Idb6S6+=46BTQ8 z0a1xY*AdOq=qp6CHF}=Nr_oWOIU1$mRoHelSEI#5^EA4Es8plth{`nj3ekLxo+nzM z(HPM}jpUE3ZC8slY9?B&(IrIX8to-oqS050mTL4Q(U}_kiRdhircRd?s+Y?bwK27RywywjX1d=&x4J}0{Gs9;3TmdArhP+xE#?xU__t^vz-NOkawf$uR zN&Q}7ERt_L7C~b9XIie*KCP!q34+9DQ36RU=O&Q&yf6h_l0f6T67e#=D-k65!U;=3 zpEzAwDXzOSf$}VK&%NA{XK6im7vxoxcTzq@`6tRL=ZUt0ax3MHlwYSjOlhkSo4J(D zlshR8RfNI+xMDBlzbMNp4UK zQSAMqeZwzWqgu2VR*Uv~)#CGClD3>55bdP_(LNavrgW8*wPBU;eXGc?5`MvI@i|QS z70NeOi=UY_67%_#x76H=^kJqa)e2uvxwlsM=WE5o%r)?AS+?e&qrehc^Hs<%Ln6Yp z-+(-0?Kh!a!E_tbJ17r`RQIeMh5XH0DR)ZUV~|C4Pl-3C&#U_h(yQuz26++Foppzi zz7jS$>h*drzAGAoEKr_?S@^UezhSS#tF|>P2mgnLAY@(R7Q-+uXguKfkNi&y{HF!} z(*pnhX@T`4I~%=5^T-b&@dZHR{YDPHF#ds&r^=ds^uJ`*s>ZVd`C{?)S+C%oUbjZ} z*%o}sc$-G2&7N$rsV6n6n!U*4P{%deGP~B|RPwjI#LEq{w^-b2qekDFJz~jFdrjo} z(d+}3OtlmHQdqiPoBah#mO6~PA<38Jdjz|Hdvv~8z9W_#^`y?X#`kASt~#c5UA}Z{ zo~pt9vgEtPmt)OW4`~$jO|up%7w%t0_gA0KIz_o~mmz4*oMqP2)LR;zKgVyKp=6IN zy3fy9XDw0(aUUw^4|BF!y{ZPgTS3$3?zEPuhqP{J?pCW$J*0JCfNrj;#x7MXU!Qxx zTBf?O7ZfyO-T~`EwHLc8LEZE2w3e%G?0E!z3Fu5!!}qIs>TmNNur9}UET*os^nmpo zwRfh8)&o_j7j)_SN`GYaE0=DwZb|^SyRAv3FEP<83x;gXYNJMZ z3&XY+^`b_L7T#M3@B!O;Rj1L*3!7{k)Lj}C zEo!oDRPsAHKGSJ$|@Jj zCpFqlbXcQ561}NW#}ctTq}%NIB~Jkz)+leOApW{5;%pufWYj}g75(Q`zlD@T2Y`-iH2JLW*)CK|mYH5II_u{^dsmw1?z4VlyI9%J zG0`v1`lGE~`84t@dkUyVqjQMT&!y$$!DWv_w^RGPa@iQrT^fCAS+>1h{Y;~8Ejt|u zp9tV5PyKw^BKsz_*Yr|hEI$wEXBy20+N_H3DHSX$&Rf3L-l=w&NcAt@YVT3^RGVHt zvwQ&PF0K0o&^C2kqqMUxw_l=)D@@DfXMfLjiE7oT@9ZX^C$*P5q3cycTK5y8LmG_{ zjcPP+g;*ZdX#I*NAbX|44|e`Q+szNjfo=rqQ}TD-M0X$Z^{Wbvo?UU3yB^4@@|(Kam51y@>ISU~!g5&Mu65hsWmvtSb=M%@u-d8X zcQf)`CNA*qyI|AjSKed4Jb@lud7ph}0zD4hPIX*+`Ja^!*soBft3-`?aOL;ySE-E} z{e9&N_G{DwCaNet=Lpb<)-62eZ}#1)1tZ{kmAC1}bDWM5wN0a2&&dMn)aagbih=4h zdib15pj8?@eoigWA29cbmlw`i2eh-yM1MHvLZJEcP4wq;zGoXz$5FairkxvtZlm^+ zb*|_x)~Mjz?aI`#FsHynG^g$eYQ<68BaM!$mY zTJ>-Oz2yk2=_O{qH|vfAU8j*z|E}XY)s#TT9oMTjHS*QljSs2fS!TWs^={+C>IRK= z)E{^3Q^z#g1@sYhm~rk=AFIzc_N!vA zOJHqpRHa05T{qWMvn6g+R};l`^5h4tq`VDtjT_a$B+HxB{X~0IbHhuHo77uGk6AW1 zEHQ3UFBC|=m(*tH4yt8^^n%i>jf3hfqCM(5=x$N@T>ti{uM(wC7E9C1E$W^rf=n+T zRU1v6Is(g&s#4~YsN0N>s$S~$sMnzTn7UB=oZcwtP?FD&smGFheq6bT9;45XtBph- zS51vQ#>dr@Tt&@xxlI)Z&AM^lZifTQS*}I-AG&2ePkfts}$riZ9aw_hE?58X_olhGVwVLy$-)?2$`DR zKz+6@wa7ZK7ydyD!Xq$y8P?r*XCv8tCKZR$9rT{*Fnv8eMXMVp%b8hKOx25GDM z1DW?qUyI$2MSY=8;_eJ1-i`^NZ{9ry20*Wl~gYw)f3HTX{ambzz+ zDUeHynUr%NUvVs=Tuxa@SxebW*+$tx*+aPp@+HSNDIcMH3i1Wxr%eBra*9Q4=0LvU zNLN)&zcywf{jyPOS=01Kq}MlXfxMvUFOWS={{TPO^sdot`B0P1xrg(7o8^|K0sB9= zHsz~GQ<^hh-Pe?fk3t@5%7qmF&G0$h*~79fWm#8HHe0^m^p<0f<)=+I+xKw(ZMGb1 zDt3O+@0(HU;bz3J8FEMSTUh(AZ0?55N1C@gpF-(7k-in)ev0%6(szqz%eR{M!rN%` z0m!GDZ*l&DaaycWiz$?IC@U#zAwTKtU|QNO;+$!Dw)u;c_fbCJY_l9`9u=Bl;)ti=WSQcITWPnLhSqEgUuAf??!Cu!> z*5`veT)(is61?1H#XGKRT$yU4eK+KV_FDYqK)ij(o{zsda1e5Zx(jlewJZmcOi1kk zvsQf^GDzkEN4gM9*2}TAGJt?k6I+!M=cT?c+}!ii$wUSMd}r$ z|0q32S<3G$9`$^-$TzcN)W)cdQERhGy=+#A)@GG@d71X=v}pZI`)TQ?Hl(H4hscM? zglQQj6Ja`{)8ao$n<$wmwK1k+@)b_0i=UQ$GJe{0IHmnVOozyaXtRfW zm`s>Vm^KkD#dCz(M`#%(AEjlKe2nQB`4}0SixIlm&MxsV)5WV#-b=fzhRB4d4Ur!qKSB>-@?qM9sXavg5N#slBeaQ7J4)>+wNdg>+C-^6 zO6^fd&W!_Qur*Rdcw29ItN}Hp!IZB(Ow29FsMs19i z%EMZF#Dnti`g&M*59{t>-96GKMYQyi@lxxhWd->P+W4vUllRkR6ZuWF2~is&AEM0& z`4QTL$%n~@X?cj+L)1p7jgXJfW|aJ>N7_6}K1!P?wMUuvC~acY#;A=^tI}EPbYAOp z)-+veYD<^87m+WbjhDQayqA_0)K*aIC*!A$pEjGQ-9&AO+7S5=ZAQqC&?ZbKOq(!m z4v{}Zn+W*``3NmXsU4*@NlG-si`f4*EEAQ&EPf7;5DVzOWsS~ zOG`h~ew~(Fn`jv#6QVZ6TqE=|LT#9Qm^NW*50O8VA-yX?ZG?P;Hlx%=nT}E$rS>R& z9;G%$K1M!9OO?rMm&q}k`Kk@I%Vg~`S-VWuj(ibqifHepjh9+4Ei1@Z(58a+e%knH zB7(gsBaa57Xul`3RW^nFwu0$&WH`lzfynQEHD;dz9K3 zwJ~aA)T%7jH;eVnVtun%U-Dk^Uh-b@73BTo{bc;qZXzEd6QVXmeuR9OOqkj*`9tI* zPOp~2c&YW1@$0nkA=-z? zhscMu6c1r)Bh*I7N618(j_R~n#+Z(gkI~+i%SdwBV!0BVmuW9~FBw16e)4`YAu=H{ zAu?et#aozsgfrKK=lYW-S@)=$e2Z9+ON z9>PqA$%knlArm1JAv4MnqhzAgM#;y>#K^?R*d{TaNm8P1lKA&B?IrIe<0s?SX|WG6 z9imN$+Ax{0PK!;1+6egw`6!vFPD@!aYGY(#)Y=LdNdcoOU_4q1vfELj7*GLRmgR!Q2g5p8E2tHRa7YU zUNT-XUfNX9zM@ceiGFJRkqMCrkqI*$)@kt{VLC#~2(?kBqdG06$C!@MGDfX! zG9#SKHk>Seyi9v_n(ao$PsUICkd|T}qBcxzSf?ddgiM4?g!WOUqvWGxVob+$nlVf< zC0lHY`0-9*R5~qMKN&wPry8b0$%knZp?!oUM#x9WM0Hwx zMrj!%6VqwNHkENsHPeifjCZP;7T(XapS+)zA*Ms*LuA5WrsagEN?Bpeh=&MmB4i@8 zi9#0VM9D;{jZV$OQ=J&KF)}gDFsf5M^3#zw85TE9+p1eVFMm`7oIX znTSqHDN&}Qw24w1LwZ_HOsB=O?Q~&mr<-ZUz_b@UX0y|U@t-dJ#IMt0>4&yBCq&B- zwIOOlGa%5<`@Hj7&_Y8QV-#GPaqF zjf{6DBP8S3QW!tAAu=J_gvf-M4wDa)i7*`@9|2RG6PYPBjUtU6NIpuNn3lrF$lK14 zNNi^?sxu@)FVkL~X3NmVPu>q6D?6DGnGh|*WWq=n=Y+|J&yW}*TulVQw24t`D`8Y6jH*ODc(r63lK0cbuhYDmvzy-r2(V znf8 zVLC)UM9Z+2Vjm_S0fTWmmotfGL>pz^D48g2qO^%=DUrlz6QkBPPjcDjG0u6S^=c`+ z7d-ZpWc;-B(=tRRq|=OwmSNh2sf}nU+6c9gc@k}ue3VR-_AxCP8+lu)lxr(xY^9RR zR?674lxV%w`eBKFrPE^LFO?l&h#o?;4^bOtI;_)dJ?4#&kC2bDtSETwD#=I5$LK9a zCPv0q#!+0x2+J57(_WosyD{yDCEAeM5Yp&xIxV@vOoz)P<}kHk=87;^M5m>cC@rI9 zY(r=fA+<5`F`Z_+%@@zM`HXPBdI*sZlL=EB z){NwhFddgyUu$AI0%89QWb)Dvqz=_&ScCUi$EGf#?4bMwq*7VgAEG!CfL zk8#*>`~-)5xAKfW|5Tr!)#v}gIUC2%aNxr&^&Ae#_q;y;9OrZ#FX;0x^!b-KyKwvp zhxk9N&%f5^Bl`RseLkwszt!j8>2pk+?(c{0DtLrq3_y^DFxNsy@G_&#&wA zA90p?yn#dFd=rPn`6nDw-#_CJ{x3MBesAgXU-kKKI7|M&>+^A(9XS4hBMryfI5Kej z6UTHM@8A%>|H2`kguaVIKKLBNfsg4}xY$_`L=nzboTYpl&hj~=9cPKdp)r2xg;@T+ zwb;4zISpt0kKgJv&+;!S3YLFpRm#u6xd>UX*f$c_;Z}JlRwERxCm#dul#Awl{lY)v((S4^~E^j ze^sLSSsKsQXP-XL(dW7PJWroX^|?%+UcG_)R$Df7PMSA${(|S@Lbs=dCzPeBJuogR_*o z4QKqXF41^9&XTWBpZjr^d^>Q)=X&Z=oQrTCz*+JS>hloJVmFL4{#Tdj^W~P^?(5y3 zc0b^L(*0}qn{JyY!!yY<%`?MO;+f}J66l@rO!%Vn7%aq-1LU@b?F`H zThcF0zdHT;^n>ZQrhhK|faCu32htx(e>wfN^sJ2XjLwX08GRW$Gp@?JZ#)!!SxZdldVlnrhA0OVIr|JLbB{X!j8n3pWSRiBqXc4&>M z2Ul8wf3F?~uCU4+V^bA2nOo#6a|+H@nM>p>bBLT}t`NNxC0OPHIm;YiQ@1tCmAnP5(@>SvJC)nkyS<6AiS zcjcajoT(m$^r{yii`A2mv((e@Fk2l%+NYj@oU6iT;tN(a0$Hl|K$fYiA?K?HV7Wj& z1i4V%i-EgH-H-HQ^)O_)8iib)d@ zfjm#yAuH59u=K0jk+)jig>*pO3%N?+A4^uN)dNV^;CF2-s#f8j1y*a6eZ(9+>+`cd zj*Ekze+JEQW+Kr(fga%I*c<1b0XJg;cNpA~3EVMowG+5Ez~Q%g;?8g$RBwa3dIFa* zL;k{ls@)mj?&eA;a(JkJd&f{uf1g^7 zKdsx*t51U})ZaJMwR5PwufMaaeRIcPm)brU>K&Nh1A3r;huYpTFxcJE+pg_W>{o`m zI|hoN85}B_TN=D#aHwnh*=L)7>$m9Qb5m_E7vuJ!Q<$^JK9r@)>>42O3)2 zTifuDCBx7k2nO3*0+m5{G`V2FzpkaWwXMCjzA4ZG-t zev>^(@%5Dr)s?M{Ep6@ES50M0^@hrpK)b(jT|;Z2MF+5^v8u6ZO~BtOK6L1HjjL<@ zm38e+EsYX!V+&%gW2wQK+9s96`z!r5fp}Hgf~|r2_NK-Sa2{-}Y(Hr#YV|%czzN)d#EC?;t*wWf=Mtw4hmxj&L z(zTRa5OXfy$x$_F$lejnU9p9dEKEwyqH&nAa3+prr*Z zB#v6*)oyRCYznkjx74mjd$u%I)uF9*A84s;2v(we^s2^nt^US(w0vt4sV_z{b&?*F zq(Yi;iBsfRafh8({-&6)Jva^N73HU*jl>^ot2e0n?rhS{F+v_wzkw(t!oXmH>|5y z?W+T=?W=0*0)dU@#o^GvSY1`yQ2icUFi_dzuW4^=f?2Q?y`VldD_Xk={#(om!JGxe zVO_wqt7>bn!B7O$T`OM4_L|y;*0`m<^r&$|U9f%Cx&~fN1-v@Y$ZDBM?V|ycO}mtZ zPTb^guW3aiwgjqcTQH8%Z*aX=2b5?ktEP#=ewg$gBm8qeQt%03GU45Nhoq>UY{(+{BfsXAmTMmi}zU%r!9le#E zodcLsSM?8ICD96hM{h5uRntzOzqhBWZ-_a1hORgTaCemevcM7r82byu3DAsH|b#X6KdnS)io-mHJU10TDg9r7HyKhI?yW1 zPGTvnsx_B7bULhZoIcF>P3KrJ^kR}S`2}lQY8%$JuWzhdhXpx#`G6mcH7<3H<|3ZB zeph#30=PyBWs;s_kh)yoIvWCAQ%X&6iJ6R3_Ey9SVDbP?|+W_y_D2&7U;A%mEMob@->so8% zs_VJVU)fYyRa=J^4KPfMQ`Ayc2I)nqq*+uuqO3%Qw)XXvby#G@^Xj_Bs>-?(Gmi6t znv%H!-Bo2%tJJr79io!H zj2)86VD+l0jyHwBu@?IUafl*p=s)UI-*5aD##`*^A_2ZXsW4(;a__m|HUMAbx`u@J2OS%TI zr0i&4xNzYj)vgs)J$;?Qp^l;9L7D0|cZ4qaAo|7clfV3Z^h@4Hzw~|dXC^Kn`Z505 zk@v1mU}tK5aNpF8)l9m4*F>Ektyqg&A2dX2rgZ~7CnXk-hk-e4wQ5ICXsXp+TtH)O zRrTs5jOi6y6?5A_rdmuEwVal)4s*tmvY}!xZx3RZl)MZ9%M>=gW@G1r#a^%0>-u{7dWL#BdV8+y z>QsY6ovOHUV4&j)86w5S#Z_$!n<|Qn{Z-X!rGLkc+U+}fySAfKa2BlY8tUlj9X$7h zELE#?o{7Gy{93W2zelc0`(VeGE^L%g?)(YV30bRj)-?^afxgSyac3Lq?HC-ydC>ef zh2pomj6ZSXi%qip`#LGx@<7A-+7_(S>&w;3;l93(?OmN^L#S}s@VOHRRBm%eXM5Mq zP}dGVK@fya-yb61Ax+iZ*L8V&Z&%;ep>C}7am)4{Lj%gZ?H}mq85&%vp8?>>0G|bz z&HeqoCwR~Wp43qyoReyG zj1vk;wFqcfMhcdqv`*wWkIabkF#{llB(+0lfG zO3_7eUArI8jyiDPJ-`P?i!erO(V;tr`V$1Zi4ZF<>+iweP-t)8zG(3>Ii0zLz31|- zj!W20r27vIV5Mp4+Jc8oxP>vFMoFJU)wcATeP;9UmMwTLl(^a{53A;Pnxiqr)Vz$v z?St)jIM7;Kg-2X|88jRs#pu>U107XY;E_@L67@l>mVF>AX^e>_R(B1C26}d&HO7?; zrKSh1HW2E*V%!3S$n-N#q(oZ2@YMRnXPsJKzUb8Y#qZ}IO*LVPT-1DK<;IQYCu;5Q zmw9ritC5f12!+0};|Turt2^rOS6_9{#wpazCRL%0FL^TnOA++Z74 zTZ#Mq;&tZy$!l4>aOalgon2ebTz+P8`I(D~Po-UaN^SWmwM&X61i3Z%0AVaYm8-KB zo>Ge{wD z__y%Z*US3F)k9%DYrt}PSyz46P-sx7 z$IVZ|)pYcA_I3?Sv`OB745-E(U48XU8+wMi>xX-XdN7D^)76Qm_dR`s<2m(yN}qa$ zwzT6JcTXpGq6@LDTXJT~-Y&^*YpA<_a7eUbXNtrI|9$KhtM%9=b;?j))!VTZ8xM0^ zmy`_?a{oYASHd+5Ihp^H8e(GnU>*~<4DVNT;@;u?3==mIr!ZXpUX41jGBo@km7(DW zsLY~8X3>Gxj=@W0WqALFTKqwqezErbzD;i$et>E%UiJYS$~64I9zQ@snI1pDRWJXb z&0`uOMt@yP<=|k~_RYOl)MA+!!hMt;1u~*=Ym9%@v#B4?N3Ouw@7WSpzF&tfkN2t? zcu9J|V!C?&>%3&i2W;#mOFw|2^o2#*)+#Er!k(voZYK?dsXea zzDxS>xJcoZO$R2pYR+t`4*xLfFm6eM!#j51Ezk@%3xbF6xZ7*MJ1Q(u+ZCQ-Y?TMsN*-Kvoe+CvMU%O6ndp#;8rjmcclB{~!kW-A zFf_bF&f;mpy5G6<%w>y~ZCO^l=&X~h`$^i9toupYldStmTCDrEc=gqS4RX)+F6lC= zb)ZK!DB$Z_lKE4_cajakcp1x1vLQ&)qHfrEjIZ&P?{Q;^Nq_uZYZIRM;f)F&{tpFq z_Q>l2{Qb!8o*_Za3J!WoZ8Tp26XcUcZVzFu{wJ z?LC8oc!6FSf5#jzGHx<|+y;G3KWM28@s?R$Q^*O;a&SB$?HZJo_&noIh@GqOHHb zH{R^Ecr%Tsf{O3L`ui>m4s~Kr*_*)r&aTink}*KFOnfp+)preS?ecebg_5pHb=T(M zt+m*c*7h}3S0$=|?m8Ii>czh)-PJ!lScOL;<0^B)#p5dTUN_O@0=S`9>-yxG6Si{0 zd<;CED?zE+!5|*Wz;H)bsAo%0SEt+}tJ>FI%*<%lo%7A-eg{HJ2 zDWRcFXq!h{dVz9#xd|jrI&C3~5=h8hG?{Q`H8hLfmD_cblB_gIll%R9?;{<_kCBFH zSJrK0|K~qvKmPsi_rL%BpM6GSiBo!XG?vbsY%&ThUm)qmLpoFhu?T3A_#BI%O0m*S z=~&3?i3n6~LM}$bB9jet@YGT=qjNnol&(_iWXfAn7s&<5RW>@!I5bZKIz&+n)X_0$ zxAK`BNsnR$0d59Yw&W(C9nzB{ONWIC4CW91-EQn5QYi{W2ZII}DhXr?0>NQ@VKKFu zFGCP48E}xy8Up}-kbnEdX?cO322b&q%QWUyLbmx97X-o|drG;S7 z8|Is(5K2&4DNG5vJ{ds>21Q|x*W3_lG}biHUj`Z0n~3I!%mZ z14dC@$YF^-Z$6Sfwirj3$Epey!?mk?0HAhkv=XDc76hPj*24>+f%M5XDL0t*Lv;;R zd^}&5GI?XPr70d0%iuB!T`snAktfmQHxuANQBP@z2|E6h;gnp2Zc4;p7FyE77F&sjGmmr>T+preiOZcSa>dh`8yU#vk4tj!%Qp=k&-f< z3Y!O5N)Vk3ePxyPqjHC0D|%G!#^-u$p8TPHk#)wG36g8Nm(BxvT%RNPMS4M#97`=G zsG(A$(^FUkqdyyU1oriClxmcAg-D5Gl=cLy%go(UPI=@!sb?5(^~GHRqsAh*XU1?h zomk*o5omo;#1gv``Me16Kr$}*6*>axCglgI5N{m9Sj|T~MjCC>E0CVNaZEogI`1_0 z?3OaKIgdlw65+iX9@N3oP{XHK41-W|H5Uk#qleRaQ9x2Lq;p}Af|y5yY5}Tn7Kw+? zoME)JkPC%kF@-YbnJ{V45ikn1(lSi*Fm_EXiqs@ed~={suikh^1a)y2^riE}bhNQp z_nHqt^Z3?5y0>=LdZUX;XnSA>LXCo`7b$WL;*ierwt|NG6$5^z7fn`VVG_G4&6KM6CgtrQ4^T@n%pRcvpG_?;khTV58drpAi>Wy+y_(3( zFQs)2#+rSpSaeR;&{%Q?ZTN1i~S0jl#sM(8PWe9CZj)1qH=JKh0+KCoAjxn?6TM@}dJ93bZ6~p?Y zH2Me$fr7V*bWwMaTQrT-DX6QPcXM_gRkn^1<)h%%BgK|6<}fu~I5aiLI!w?o*0MOqE_K{iJ_E71GRE+vGvBC@!6Dz;-$6hv$sSR7l-%#&EU zQ@ZA~8i&JasAy!fEi0PnDWyjl)AcC2lr$>g%bqeLn`*ku=(%Kd7VPz{7>c{bU{KQr zgL&U*sDCL%@|{?+gtjln5VW{Qn}>Ttp_>kqesv47CU*5pN_Zq)Q0-;%3_!1_%eJgD&+CqTp)G+Fj zwYyUn+&;2wf4R(D9F+@?Alq}0uf2;)8}Z*J_vY@MDu)RzUkT+zGpBb^tZQZp1tZAC zvT@Nw#PB+ufSDDH3m2DC5uHJs#ubCpJpo~s)hY(@Qh+(SX#t7*o zw%xlk#Odw!_8Mj4+xmC2?KcJ+8^`zc_8t>U(~ww$he8l)wEmS9l0K#rv``u#29x4S zy7$ci^f>n|j(ALuh*-HBXf(K%LTDa#D6#yOSED9mww>zG9GWz7Wak9!37H;2IRtx^ z5>w)FNe@>}cnEc6g~#GnuvS_kw9YUFg(Wm8KEYmsoT6G{37ckv{K4?&>7&9Hkd5Rl z&k!*3DL5mao$4~b-;AXISz_g*A;UYgU{k~iJ-rw=?9{kXtD)IbH4Q6ND%bsF>w0Yu zTj0iQQ;Vmd42FI5Ew?dl(M3CHQ;Wy31>FxN12b->7IVHViq(EbM+AuM#s(M)hij#2 z4L1~ zR4ZD$Z?-AyYtuEqzo}Vk@wYW=fwq}e%^z;nXTohW(HS3%$9T}lO!I7;zqwfp&m0VE zO-<2etv%90hG-FA%WU|dFMP0Q)vjqP5p5x!MB18YHNd#zolNISY?8!aTwSGKw3F<+}1>sGni z6)R)Yf|fQoOpE+N3g9-szTQ5P2qQ=@@Il-}F;4(qTze48t9>qzx1&B38oB^>>*R}) z<-|q5=fc4mpah?+wPmrh3VPu*>9r+; zawFFcrVGtlk_FZ*T$fgCF_C6PW+psTp-D#?_Ay(Td5~){Ju?45veNou8)FZXg++mZ z1yUm4!Nd9(UaHw~B6vt&u;0UwhM<#A$vxcoEh#VguqN7HR;0;LHnB;Fxl3k_Qe86O* zRCJP?G+AQrH-aM*+$>WV14D}vA ze_x;Rmxl|}x$sGIg-KmFycWwJgcnW=JuJ+q#B0g2G#2D$zAz)8ibH7^8VaE4Z*n80 zO-7rgLzUvpFf?O_3`0TwiUaqRhKj6<)OOhShDjY>h3F|xqxc!>Q=#mF-6mo|ue6vb z*pd)kb}Rb=L>&#ILWf{XJS>k5ycvfAGMoxBlF;9W7bNI}r>R9lKPOuA)S?WGH6{fe zGy)nnpSilDGLoCnFfLuz$EZ;v>(nKsc{K$Y73T`j?UC786qiv<^NT5IH1s zVN>CZB$lDYWP=My)VH*f&Y2O*XA}?i0#MpI^!0PFSm&i~|rHuo&H5R8J$aVGnOXk#+ZQ+R-t8 z>}QKC!IqiMu#LsgQSqd*Sv)PW1>7Bn8;nkIDC;~6!&SxJ+aj)q*%FK6KF0dkDzMID zh4CE6eH4eps`wk{Phn6d{|IR4xSqm&hToGLrAYDVs^V$ZY?6BcC2iGug6bH{P zaz5g~5x7x$Do+8Y(aErBq|btrcsj#<1=T`oI$J?}9e>!51%(kd#-^Btob|F36#v47 zvsEF8;@MnmvtacXsBo;;F~y2ZT04-@7kZKZ1WJNRh{{97Rg_MWm#JtKRNfKPdkTLd zR2a2IF+{td+ErN+PcgI|YAvhVP@>uoBPP{<7!;{}P^w0&=*O|c@4@o|>Nv_<8c`NS zYZRpMOzj|yP>pn~?%Kghb_Y%+z6+-dtGH{zT_w&frau+md(UvT@(ryNW<_kG+gw0x zkT*x8$(BQDCyp*$4S9YJ?!Zs!bd;;cQ2a*K4{oY>wmKy{>(db!T?Ie8~Y>O^OV+V~6c$Wa}(-8g_{Nwj;sU5lH@s8JAOKrZ>wR?_QVn2NSU3dIN?N7#bCm!)U{K(XE$8UQ0 z`!6s3VdaOswXZy`U-Qk+eDQmaezpGi(?3o;a@l7VKU({hzj`v|j6L_c?+mcMk4#+E z@eNnz0cX<}0>>V28*8n7ez~sx!Qb7J`bkg!9iM&urN8*#=kEHiwKqQ(pZ?8}`=e_^ zU%1Nt$*zG%n(n@@_IoR@yB1#gt^eix_X?m_A2z(y>_?rH9AI=Wd72{)OW)Dm zOi{CsR;!1t>S6a@$zoj6h^yKA!Gq_XxZ$%QeKriAjXH`$Po8@=dtOeSM!FlE)UyVu zvy#+VgVb3YQ(SHrvno|67ngfCB2T+S8MvyDgK4G8YCKmmi(7hmnBo>RP_7`lYV)9s zjw-y2k$K>OYS20=^V~%xQcFS14it(z;$|4YLy;pVW_GOff|sM@Wez5SiYh)Qvv$sP z8HzVo0OzXdsR|{{8TH(A&O_ycnCE4L^Mw)4*YF6)Q7+1PLBnuDR3zb+-f+ctVbp1h z3*U69$^HQUC{xAlz@r-vc0AOqx!g?gtnD?5eVlll=0#EES&zEt31zn)1*w{~`WmVQ zlTB;`m1(3b?bl)$VnF$T`U&6lY6XZ1X`)EgFnS)_pIM% zv0Df~VY63NIW2aV-7bpDjzWR^0~PkGvfl$4&-#N7y7jC-$O)6C@$GELf8TA_^2n4>} zHaofQ&$+I-C>Aw!i@gq>_r40=6_1N}bna3Wr11&ma(vK)94c*0QM?t*V)1%yDq0er zy>5DTBU1>36f7>4@j2si<^Uh4ekY<@P#CPfCi_YSL&aD!g>#bBQp0#T| zYuAA|+7}Y`3Wkvcp1p2$m*R3bD&!ALDs@h9x7O}i>qccNbzU*v^kOvfV!**a96W2S zbpnw$+*^^f;>5iZC5!tyuan9jMcNML>fFF~%2Peh$yz&7cUB|3#arzK2@4+339R%) zk4jy&h3d<*HjS=Kg$;KqgS7>eh8JF*wHTTlbx%dfKL7vA`f#oJm&-$;3n^oHXsf`m zSF?MM1rxdRR#Ei7{{MO{5s07!!%sGF-Svnt8h5D2v?D#6R(8F z{U8OwE$6twiF@vOHs^9SAM7j~vyTpv7+CGFa;lhvgoD+gxWI~)7gaUC);gqETj{XW z+$AJj?&0OvI-^*pDd=GohDIcV@E<}tzCbI$32 zc<9DWmCUFi_}Lvcr_<#Et=x1#5zbdStX!rvZuvCgbjsLnnoHztfSJZix$=sdsCL-I zjkvmtLCnHYrV71X>%wwBfA_{9%BS?D(o~NA;#ct6gzI|v1YK^;czGHa%hfpDTt4QR0Cv`dgh>NR0=tN86!b#1&&l7|Hih9ld8;L13_r565 z%Pxn#z7CTgra$ifDgvD}6KCg@!b8_$jf*L>R=uW(>S*b8xn%e-i->z}^D;UGke zhqEkSmMaI@z?GBnUTl1Y_J&6d&O)gx#+OgY-Y1r#^3gmS-te8P9b->8t4_uGy63vV!wpl)Ai6_2j8oQkdId*A3fAiVace>zW}T ze$#8*^zoZR3VUZGoqwN_TWSa7X++)2EsgkS+?2aE=S5rB@$f2b5>`_jHRq$Y-~*kI zjhKZK&Hi4alD)U+m?85?Z;i&GHL&q1J|XUaih~9gQ#ifufNJmpR_O15DvxFBPUuV6 zHj5un$8q9zEOMj1%HJ61p7FzgIMUkI)PAr<_XXN(lugC8=5Mt8VlcM{%x$i*Uku*1 zD7cBqfyt9!uD&|>Vy5@mYrgoHb=~uIs_&aSZWZP(x8@rCt@5S#yh~#;Izw#(O$xn( z*(7#Kyj$XGiEAbHN?a$gD)Byv_e*?0VxPn<5(gyik~k#sfW*TRk4ii)@sz|TB)(PR zlM+WIo|iZ-aZ=)p#48ftDREZfdnLY4;s+#tP~wLqenR4>C4NTYXC>Z{_^iawOZ=k5 zFH8KY#IH$wPU7Sp0`Vh1HeHoJ{gWHNJ-15~5`xxA|`aKUC zUGV=)#CsTUCtw~h1?T|m1GoV{L%25pe*$<65C_}|cmObg`1H#n%`QCe1JnWB02|;u z++PB00G{6NJlnRu|h zmckeNp0MOz=3`Ih@9|>aUn{0p+E|l<7kHD&6OklddgE`aO~OSOoMm970xCGGJ%M>V zjawL*z$}ch-?YJ^lp8kPg3vHS6b6^<8mo9!^98H4;Ve9BmR$`l`TKVAJ>66bUZPuA zfK}vA6v__HPQgi>bNJxJJl?Hi?0*-%p!j7n7%{!j_+1MOK8yqPauy>`*~BY(|77+p zHY;JTGYBbkDupmv9*xc58xgDYCUcs7%6fE3Pw}t)kzorC(d3p#c$e=(78s38#UiJK zDH2K(&(aJ?5P}5|`=ZHJTK>R!mEsCfX9{Nv_oh+eI^D4i+Z0JRm>Y3MBDa%bY-2MG z_BGpd0#-73wK9J^j;uEJ$F@m2xNSRcE158f!i7Om8t0M}9tzC936s}NZ$sjAkKPlo zhsD9qup`DkGTvo8Cf(q$LeJB9MvxIapF=H@H7{c!w2L7U6bs&j^i*v1Hs+i)_hzQ) zz0GC%z(mS8HHiy)x-QLZc!w}u{`nm}_&PB}27FwddJBEuoZuPsnKuDmxW9~#%c~H( zp8$RWA3{HgkDrI|h2WF;!f>`8a5ZBeZ@{w(clh@pP6qIKzz+d^*C=cS@L9kQ0Db!u zmIQnX@HGGl+!jc-HdcY}Q9B@lyRc`utH?x1+v$KW-lmG|Zt>30+W$akP+Oe-;uK++3V0Qqp?6&U$ zVC=D925{3-w&g?1012JkL`3vfAL58w)b z7qAzA;feGLb_`*53|)2%VRnc|{5STU(C41q`-K7Ui1CQNJkRX=0oMYcBCx*)a2)_* zoBeu#56}caz1j}~S^%wpHh>=x0JH--03(1K05<|g0r=Rw9Rsg@3NQ^g0O$ks0|o$t zfFZykz%bx2U<_~s01?cN57*l}0bKxmuioAR2m(TYUcfQHali?{O@Lbfw*qbhyccj1 z5C+TuB7i7h7BB~x2S9|dF8~$+Hv=?)4u}D62gCshKpKz%ECEgfmH{Zb9e+0NYsHAq z7|J(`x@O2@7Inl<0t4}%2xsB*(hA(EP9EIkFXpXJZ{beiH@0whf$(cQ1#uDSV1-V=1L^?h9Jb)fWr2}-FV(VsIUgaH=alFe6!gfekvdYfTW8nm?q}8 z{AERsvRQ^Z0RG4cmyL}Lxcr>|Gb|x+2f!aWi6sSG-p22A!7phWDEK99vL6Zb)-Run z%i})t@7~SjH){OGUV3RHleE2P{+&g;GXFwlS7ZS@c-TO5%l`X;74#kEG||`j!c+w| z+Bw2(^UG4>riLvLuDC6$ojYW6m8Ev*2xsO;7mbHS^&J`&)pF>pAiM!C3x3qqvIQhR82a7@sJo@%EqVZI08OyXeJ)QG3d*@E5AJv!jxEiNxcS9I&VbB{LsRnf^)*GQ0 zU%DG+!|}A<(9?B&j&@<>9DP%WO{sTXU%+eE^|?$Vde`+vdG?HBNj5-V$3B7O8^8JG z^Q9>d>im#h*o^OYd|&c?-`CJI(R6pyV@+Rb`iG{z=BJu12WJjG)$-LAOKU@GU+YZk z-K~$ceyP>c_SLp#|3v#^?R_0jbu@I&blu%O)6*9OAr)&?^oJQAs5B@1EB?Fucl#gq z|B?T%{a^E+_y41RSD-fVtAXyoMBsSfw!l*0OyD;H9|?Rc@P~oV1~vk(2EH4xwO6*+ zw|BRXwcpepZoj|%!S)ZgKhpk*_CIg`Li@S)e`;4craIO-Ug-E?hpn@!b5G~~&hF0P z&i8gMcV;`E>-#hLbauJBYP+84damm$UH_*`>2`D{x-;Epy0hKC-Ti3ylie?M zU)iJf_1%)NbpqfbTAuS4}Ku{;o$EFKNI|K!OsT29Q;b~>%ngZzZd)wm4%PN z0Gx1xug^E*`wic>eSg#Z?Phz+RLkovKW~|B{bB2&wvV^%^GE%6`XBK>?f(~lW8i&( zM+1Ks_-Wu>?a}uC+5Xe^M?1dLvA^>~=iOaD>uTuk>$dm2x96pvcLr|{{z33xf+V2a zi6rWMhkZ%k@A>|R@9%xAX>u+_`ET~0^w0X^ z{*=EWuq)sRToI@bTobr9fJD)7yg*O*&Ne;Yw7a>wd8+vYEvTv$hV=mpbq{xscF%X; Q+kGFz;a~oK5li6z0m1%nDF6Tf literal 0 HcmV?d00001 diff --git a/native/WpfBridge/bin/wpfbridge64.dll b/native/WpfBridge/bin/wpfbridge64.dll new file mode 100644 index 0000000000000000000000000000000000000000..ab73fbd8c29167d47bd4c099498f2aec7e8f0b1a GIT binary patch literal 88576 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 x-j6+~)AO //using namespace msclr::interop; + +using namespace System; +using namespace System::Windows::Automation; +using namespace msclr::interop; +using namespace Globals; + +JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_SetFrameworkId(JNIEnv *env, jobject obj, jstring jpropertyValue) +{ + const char *propertyValue = env->GetStringUTFChars(jpropertyValue, 0);//convert string + Global::WPF_AUTO->setFrameworkId(marshal_as(propertyValue)); + env->ReleaseStringUTFChars(jpropertyValue, propertyValue); //release string +} + +/* + * Class: org_synthuse_WpfBridge + * Method: CountDescendantWindows + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__(JNIEnv *env, jobject obj) +{ + return Global::WPF_AUTO->countDescendantWindows(); +} + +/* + * Class: org_synthuse_WpfBridge + * Method: CountDescendantWindows + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + jint result = Global::WPF_AUTO->countDescendantWindows(marshal_as(runtimeIdValue)); + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return result; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: CountChildrenWindows + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__(JNIEnv *env, jobject obj) +{ + return Global::WPF_AUTO->countChildrenWindows(); +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: CountChildrenWindows + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + jint result = Global::WPF_AUTO->countChildrenWindows(marshal_as(runtimeIdValue)); + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return result; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumChildrenWindowIds + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumChildrenWindowIds(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + array ^mchildrenIds = Global::WPF_AUTO->enumChildrenWindowIds(marshal_as(runtimeIdValue)); + + //create result object array to the same size as the managed children Ids string array + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); + marshal_context context; //lets you marshal managed classes to unmanaged types + //char **childrenIds = new char *[mchildrenIds->Length]; + for(int i = 0 ; i < mchildrenIds->Length ; i++) + { + //childrenIds[i] = (char *)context.marshal_as(mchildrenIds[i]); + //env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0) + env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as(mchildrenIds[i]))); + } + //delete[] childrenIds; + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return results; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumDescendantWindowIds + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + array ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds(marshal_as(runtimeIdValue)); + + //create result object array to the same size as the managed children Ids string array + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); + marshal_context context; //lets you marshal managed classes to unmanaged types + //char **childrenIds = new char *[mchildrenIds->Length]; + for(int i = 0 ; i < mchildrenIds->Length ; i++) + { + //childrenIds[i] = (char *)context.marshal_as(mchildrenIds[i]); + //env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0) + env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as(mchildrenIds[i]))); + } + //delete[] childrenIds; + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return results; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumDescendantWindowIds + * Signature: (J)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__J(JNIEnv *env, jobject obj, jlong jprocessId) +{ + array ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds((System::Int32)jprocessId); + + //create result object array to the same size as the managed children Ids string array + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); + marshal_context context; //lets you marshal managed classes to unmanaged types + for(int i = 0 ; i < mchildrenIds->Length ; i++) + { + env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as(mchildrenIds[i]))); + } + return results; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumDescendantWindowIdsFromHandle + * Signature: (J)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIdsFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle) +{ + array ^mchildrenIds = Global::WPF_AUTO->EnumDescendantWindowIdsFromHandle(System::IntPtr(jwindowHandle)); + + //create result object array to the same size as the managed children Ids string array + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0); + marshal_context context; //lets you marshal managed classes to unmanaged types + for(int i = 0 ; i < mchildrenIds->Length ; i++) + { + env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as(mchildrenIds[i]))); + } + return results; +} + +/* + * Class: org_synthuse_WpfBridge + * Method: GetProperty + * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_GetProperty(JNIEnv *env, jobject obj, jstring jpropertyName, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + const char *propertyName = env->GetStringUTFChars(jpropertyName, 0);//convert string + System::String ^mresult = Global::WPF_AUTO->getProperty(marshal_as(propertyName), marshal_as(runtimeIdValue)); + marshal_context context; //lets you marshal managed classes to unmanaged types + jstring result = env->NewStringUTF(context.marshal_as(mresult)); + env->ReleaseStringUTFChars(jpropertyName, propertyName); //release string + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return result; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: GetProperties + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetProperties(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + array ^mprops = Global::WPF_AUTO->getProperties(marshal_as(runtimeIdValue)); + + //create result object array to the same size as the managed children Ids string array + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0); + marshal_context context; //lets you marshal managed classes to unmanaged types + for(int i = 0 ; i < mprops->Length ; i++) + { + env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as(mprops[i]))); + } + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return results; +} + + +/* + * Class: org_synthuse_WpfBridge + * Method: GetPropertiesAndValues + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetPropertiesAndValues(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +{ + const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string + array ^mprops = Global::WPF_AUTO->getPropertiesAndValues(marshal_as(runtimeIdValue)); + + //create result object array to the same size as the managed children Ids string array + jclass stringClass = env->FindClass("java/lang/String"); + jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0); + marshal_context context; //lets you marshal managed classes to unmanaged types + for(int i = 0 ; i < mprops->Length ; i++) + { + env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as(mprops[i]))); + } + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return results; +} diff --git a/native/WpfBridge/org_synthuse_WpfBridge.h b/native/WpfBridge/org_synthuse_WpfBridge.h new file mode 100644 index 0000000..e6d8f07 --- /dev/null +++ b/native/WpfBridge/org_synthuse_WpfBridge.h @@ -0,0 +1,115 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_synthuse_WpfBridge */ + +#ifndef _Included_org_synthuse_WpfBridge +#define _Included_org_synthuse_WpfBridge +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_synthuse_WpfBridge + * Method: SetFrameworkId + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_SetFrameworkId + (JNIEnv *, jobject, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: CountDescendantWindows + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__ + (JNIEnv *, jobject); + +/* + * Class: org_synthuse_WpfBridge + * Method: CountDescendantWindows + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__Ljava_lang_String_2 + (JNIEnv *, jobject, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: CountChildrenWindows + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__ + (JNIEnv *, jobject); + +/* + * Class: org_synthuse_WpfBridge + * Method: CountChildrenWindows + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__Ljava_lang_String_2 + (JNIEnv *, jobject, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumChildrenWindowIds + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumChildrenWindowIds + (JNIEnv *, jobject, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumDescendantWindowIds + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__Ljava_lang_String_2 + (JNIEnv *, jobject, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumDescendantWindowIds + * Signature: (J)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__J + (JNIEnv *, jobject, jlong); + +/* + * Class: org_synthuse_WpfBridge + * Method: EnumDescendantWindowIdsFromHandle + * Signature: (J)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIdsFromHandle + (JNIEnv *, jobject, jlong); + +/* + * Class: org_synthuse_WpfBridge + * Method: GetProperty + * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_GetProperty + (JNIEnv *, jobject, jstring, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: GetProperties + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetProperties + (JNIEnv *, jobject, jstring); + +/* + * Class: org_synthuse_WpfBridge + * Method: GetPropertiesAndValues + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetPropertiesAndValues + (JNIEnv *, jobject, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/native/WpfBridge/resource.h b/native/WpfBridge/resource.h new file mode 100644 index 0000000..d5ac7c4 --- /dev/null +++ b/native/WpfBridge/resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc diff --git a/src/org/synthuse/Api.java b/src/org/synthuse/Api.java index 6896e2d..0cb236d 100644 --- a/src/org/synthuse/Api.java +++ b/src/org/synthuse/Api.java @@ -2,7 +2,7 @@ * Copyright 2014, Synthuse.org * Released under the Apache Version 2.0 License. * - * last modified by ejakubowski + * last modified by ejakubowski7@gmail.com */ package org.synthuse; diff --git a/src/org/synthuse/CommandPopupMenu.java b/src/org/synthuse/CommandPopupMenu.java index aca4309..ca5d3bb 100644 --- a/src/org/synthuse/CommandPopupMenu.java +++ b/src/org/synthuse/CommandPopupMenu.java @@ -2,7 +2,7 @@ * Copyright 2014, Synthuse.org * Released under the Apache Version 2.0 License. * - * last modified by ejakubowski + * last modified by ejakubowski7@gmail.com */ package org.synthuse; diff --git a/src/org/synthuse/WpfBridge.java b/src/org/synthuse/WpfBridge.java new file mode 100644 index 0000000..75c65ee --- /dev/null +++ b/src/org/synthuse/WpfBridge.java @@ -0,0 +1,90 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + +package org.synthuse; + +import java.io.*; + +public class WpfBridge { + + static + { + String archDataModel = System.getProperty("sun.arch.data.model");//32 or 64 bit + + //System.loadLibrary("native/WpfBridge" + archDataModel); // WpfBridge32.dll (Windows) or WpfBridge32.so (Unixes) + loadNativeLibraryFromJar("/wpfbridge" + archDataModel + ".dll"); + } + + public static void loadNativeLibraryFromJar(String path) { + // Obtain filename from path + String[] parts = path.split("/"); + String filename = (parts.length > 1) ? parts[parts.length - 1] : null; + // Split filename to prexif and suffix (extension) + String prefix = ""; + String suffix = null; + if (filename != null) { + parts = filename.split("\\.", 2); + prefix = parts[0]; + suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null; + } + File temp = null; + try { + // Prepare temporary file + temp = File.createTempFile(prefix, suffix); + temp.deleteOnExit(); + } catch(Exception e) { + e.printStackTrace(); + } + if (!temp.exists()) { //some reason the temp file wasn't create so abort + System.out.println("File " + temp.getAbsolutePath() + " does not exist."); + return; + } + + // Prepare buffer for data copying + byte[] buffer = new byte[1024]; + int readBytes; + // Open and check input stream + InputStream is = WpfBridge.class.getResourceAsStream(path); + if (is == null) { //check if valid + System.out.println("File " + path + " was not found inside JAR."); + return; + } + // Open output stream and copy data between source file in JAR and the temporary file + OutputStream os = null; + try { + os = new FileOutputStream(temp); + while ((readBytes = is.read(buffer)) != -1) { + os.write(buffer, 0, readBytes); + } + os.close(); + is.close(); + } catch(Exception e) { + e.printStackTrace(); + } + // Finally, load the library + System.load(temp.getAbsolutePath()); + } + + native void SetFrameworkId(String propertyValue); //default is WPF, but also accepts Silverlight, Win32 + + //Descendants will walk the full tree of windows, NOT just one level of children + native int CountDescendantWindows(); + native int CountDescendantWindows(String runtimeIdValue); + + native int CountChildrenWindows(); + native int CountChildrenWindows(String runtimeIdValue); + + native String[] EnumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop + native String[] EnumDescendantWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop + native String[] EnumDescendantWindowIds(long processId); + native String[] EnumDescendantWindowIdsFromHandle(long windowHandle); + //In all the above Enumerate methods will return a list of Runtime Ids for all related windows. + + native String GetProperty(String propertyName, String runtimeIdValue); + native String[] GetProperties(String runtimeIdValue); + native String[] GetPropertiesAndValues(String runtimeIdValue); +} diff --git a/synthuse.properties b/synthuse.properties index 06a1f84..9fea982 100644 --- a/synthuse.properties +++ b/synthuse.properties @@ -1,5 +1,5 @@ # -#Tue Mar 25 12:56:37 EDT 2014 +#Thu Apr 03 22:00:23 EDT 2014 DEFAULT_PROP_FILENAME= urlList= xpathList=